Message ID | c4f9d238a08b5c8de6c14e86cfbe3fe8b8a55f4f.1570720648.git.leonard.crestez@nxp.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | soc: imx8mq: Read SOC revision from TF-A | expand |
On 19-10-10 18:19:03, 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> > > --- > This was discussed previously and but nothing was merged. I'm having > trouble finding email archive links but here's one: > > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.kernel.org%2Fpatch%2F10935599%2F&data=02%7C01%7Cabel.vesa%40nxp.com%7C71f4817b96664652f41d08d74d95327d%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637063175494533275&sdata=QyDT2NyNYVIY0OCxxscL4RkW2iNUVOuRK5OeVOz%2BP%2Bc%3D&reserved=0 > > NXP vendor tree always used TF-A for this and from previous discussion > it is reasonable to rely on firmware for workarounds. > > The SMC call has been in TF-A upstream for a while. > > drivers/soc/imx/soc-imx8.c | 28 +++++++++++++++++++++++++--- > 1 file changed, 25 insertions(+), 3 deletions(-) > > diff --git a/drivers/soc/imx/soc-imx8.c b/drivers/soc/imx/soc-imx8.c > index b9831576dd25..20af442a247a 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 > @@ -35,10 +38,22 @@ static ssize_t soc_uid_show(struct device *dev, > return sprintf(buf, "%016llX\n", soc_uid); > } > > static DEVICE_ATTR_RO(soc_uid); > > +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; > +} > + > static u32 __init imx8mq_soc_revision(void) > { > struct device_node *np; > void __iomem *ocotp_base; > u32 magic; > @@ -49,13 +64,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 b9831576dd25..20af442a247a 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 @@ -35,10 +38,22 @@ static ssize_t soc_uid_show(struct device *dev, return sprintf(buf, "%016llX\n", soc_uid); } static DEVICE_ATTR_RO(soc_uid); +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; +} + static u32 __init imx8mq_soc_revision(void) { struct device_node *np; void __iomem *ocotp_base; u32 magic; @@ -49,13 +64,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);
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> --- This was discussed previously and but nothing was merged. I'm having trouble finding email archive links but here's one: https://patchwork.kernel.org/patch/10935599/ NXP vendor tree always used TF-A for this and from previous discussion it is reasonable to rely on firmware for workarounds. The SMC call has been in TF-A upstream for a while. drivers/soc/imx/soc-imx8.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-)