Message ID | 681dff4de9d3d0cb045b0a5883b02c04bbd2486f.1572391028.git.leonard.crestez@nxp.com (mailing list archive) |
---|---|
State | Accepted |
Headers | show |
Series | [v2] soc: imx8mq: Read SOC revision from TF-A | expand |
On Wed, Oct 30, 2019 at 01:17:39AM +0200, Leonard Crestez wrote: > 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> > > --- > Changes since v1: > * Add ifdef to fix build on ARM older than v7 (kbuild robot) > Link to v1: https://patchwork.kernel.org/patch/11183813/ > > Alternatively a CONFIG_IMX8M_SOC config option could be created which > depends on HAVE_ARM_SMCCC but that also requires defconfig changes. > > drivers/soc/imx/soc-imx8.c | 32 +++++++++++++++++++++++++++++--- > 1 file changed, 29 insertions(+), 3 deletions(-) > > diff --git a/drivers/soc/imx/soc-imx8.c b/drivers/soc/imx/soc-imx8.c > index fcbf745a9971..6a2916664438 100644 > --- a/drivers/soc/imx/soc-imx8.c > +++ b/drivers/soc/imx/soc-imx8.c > @@ -7,17 +7,20 @@ > #include <linux/io.h> > #include <linux/of_address.h> > #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 > > #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 > > /* Same as ANADIG_DIGPROG_IMX7D */ > #define ANADIG_DIGPROG_IMX8MM 0x800 > @@ -27,10 +30,26 @@ struct imx8_soc_data { > u32 (*soc_revision)(void); > }; > > 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 u32 imx8mq_soc_revision_from_atf(void) { return 0; }; We may want to have an inline for it. I added it and applied the patch. Shawn > +#endif > + > static u32 __init imx8mq_soc_revision(void) > { > struct device_node *np; > void __iomem *ocotp_base; > u32 magic; > @@ -41,13 +60,20 @@ static u32 __init imx8mq_soc_revision(void) > 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; > + /* > + * 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; > soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW); > > -- > 2.17.1 >
diff --git a/drivers/soc/imx/soc-imx8.c b/drivers/soc/imx/soc-imx8.c index fcbf745a9971..6a2916664438 100644 --- a/drivers/soc/imx/soc-imx8.c +++ b/drivers/soc/imx/soc-imx8.c @@ -7,17 +7,20 @@ #include <linux/io.h> #include <linux/of_address.h> #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 #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 /* Same as ANADIG_DIGPROG_IMX7D */ #define ANADIG_DIGPROG_IMX8MM 0x800 @@ -27,10 +30,26 @@ struct imx8_soc_data { u32 (*soc_revision)(void); }; 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 u32 imx8mq_soc_revision_from_atf(void) { return 0; }; +#endif + static u32 __init imx8mq_soc_revision(void) { struct device_node *np; void __iomem *ocotp_base; u32 magic; @@ -41,13 +60,20 @@ static u32 __init imx8mq_soc_revision(void) 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; + /* + * 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; soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW);