[U-Boot] [PATCH v2 1/2] imx: mx6: add get_cpu_speed_grade_hz func to return MHz speed grade from OTP

Tim Harvey
2015-05-15T13:42:57Z

On Fri, May 15, 2015 at 12:53 AM, Christian Gmeiner
<christian.gmeiner@gmail.com> wrote:
> Hi
>
> 2015-05-14 7:08 GMT+02:00 Tim Harvey <tharvey@gateworks.com>:
>> The IMX6 has four different speed grades determined by eFUSE SPEED_GRADING
>> indicated by OCOTP_CFG3[17:16] which is at 0x440 in the Fusemap Description
>> Table. Return this frequency so that it can be used elsewhere.
>>
>> Note that the IMX6SDLRM and the IMX6SXRM do not indicate this in the
>> their Fusemap Description Table however Freescale has confirmed that these
>> eFUSE bits match the description within the IMX6DQRM and that they will
>> be added to the next revision of the respective reference manuals.
>>
>> These have been tested with IMX6 Quad/Solo/Dual-light 800Mhz and 1GHz grades.
>>
>> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
>> ---
>> arch/arm/cpu/armv7/mx6/soc.c | 41 +++++++++++++++++++++++++++++++
>> arch/arm/include/asm/arch-mx6/sys_proto.h | 1 +
>> 2 files changed, 42 insertions(+)
>>
>> diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c
>> index dd34138..71fa1fb 100644
>> --- a/arch/arm/cpu/armv7/mx6/soc.c
>> +++ b/arch/arm/cpu/armv7/mx6/soc.c
>> @@ -83,6 +83,47 @@ u32 get_cpu_rev(void)
>> return (type << 12) | (reg + 0x10);
>> }
>>
>> +/*
>> + * OCOTP_CFG3[17:16] (see Fusemap Description Table offset 0x440)
>> + * defines a 2-bit SPEED_GRADING
>> + */
>> +#define OCOTP_CFG3_SPEED_SHIFT 16
>> +#define OCOTP_CFG3_SPEED_800MHZ 0
>> +#define OCOTP_CFG3_SPEED_850MHZ 1
>> +#define OCOTP_CFG3_SPEED_1GHZ 2
>> +#define OCOTP_CFG3_SPEED_1P2GHZ 3
>
> Note: 0x3 is defined as reserved (IMX6DQRM Rev 2, 06/2014).

Right - this goes back to the fact that the RM's are full of omissions
in this area. I've gotten confirmation of sorts from Freescale that
the above is what is used. Still, I would love to see some testing and
I only have 800MHz/1GHz ranges, so if anyone out there with a IMX6DUAL
or IMX6QUAD at 1.2GHz could verify this works please do.

>
>> +
>> +u32 get_cpu_speed_grade_hz(void)
>> +{
>> + struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
>> + struct fuse_bank *bank = &ocotp->bank[0];
>> + struct fuse_bank0_regs *fuse =
>> + (struct fuse_bank0_regs *)bank->fuse_regs;
>> + uint32_t val;
>> +
>> + val = readl(&fuse->cfg3);
>> + val >>= OCOTP_CFG3_SPEED_SHIFT;
>> + val &= 0x3;
>> +
>> + switch (val) {
>> + /* Valid for IMX6DQ */
>> + case OCOTP_CFG3_SPEED_1P2GHZ:
>> + if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D))
>> + return 1200000000;
>> + /* Valid for IMX6SX/IMX6SDL/IMX6DQ */
>> + case OCOTP_CFG3_SPEED_1GHZ:
>> + return 996000000;
>> + /* Valid for IMX6DQ */
>> + case OCOTP_CFG3_SPEED_850MHZ:
>> + if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D))
>> + return 852000000;
>> + /* Valid for IMX6SX/IMX6SDL/IMX6DQ */
>> + case OCOTP_CFG3_SPEED_800MHZ:
>> + return 792000000;
>> + }
>> + return 0;
>
> Do we really need the ifs inside the cases? The speed grading fuse
> value is read only and
> we must simply life with the value we read back. So I would drop the
> is_cpu_type(..) thing.

I've had a bit of a difficult time getting verification from Freescale
that all IMX6 CPU's use the exact same OTP register and setting for
this which is why I'm asking for testing. I haven't gotten a simple
'yes' to that question but instead of been giving small snippets of
information. Not a single one of the RM's agree's with the other in
this area (most marked as reserved or omit the register or omit the
values altogether)

My personal feeling is that the speed grades (and temp grades for that
matter) are the same for all IMX6 and even though the datasheets for
the IMX6SDL/IMX6SX state they don't 'sell' a 850MHz or 1.2GHz speed
grade we should honor the setting (meaning I agree with you that we
should remove the if's).

Tim