: imx: mx6: use OTP for freq grade
Subsystems (2)
v2 cover : imx: mx6: use OTP for freq grade
This is a second take on my last series to obtain and use CPU frequency grade in print_cpuinfo().
--
v2:
- split into two series: 1 for CPU frequency, other for Temperature grade
Tim Harvey (2):
imx: mx6: add get_cpu_speed_grade_hz func to return MHz speed grade
from OTP
mx: mx6: display max cpu frequency in print_cpuinfo()
arch/arm/cpu/armv7/mx6/soc.c | 41 +++++++++++++++++++++++++++++++ arch/arm/imx-common/cpu.c | 16 +++++++++++- arch/arm/include/asm/arch-mx6/sys_proto.h | 1 + 3 files changed, 57 insertions(+), 1 deletion(-)
Signature · 1 line
1.9.1
PATCH v2 1/2 imx: mx6: add get_cpu_speed_grade_hz func to return MHz speed grade from OTP
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.
--- arch/arm/cpu/armv7/mx6/soc.c | 41 +++++++++++++++++++++++++++++++ arch/arm/include/asm/arch-mx6/sys_proto.h | 1 + 2 files changed, 42 insertions(+)
arch/arm/cpu/armv7/mx6/soc.c +41 -0
@@ -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 + +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 ; +} +#ifdef CONFIG_REVISION_TAG u32 __weak get_board_rev (void ) {
arch/arm/include/asm/arch-mx6/sys_proto.h +1 -0
@@ -16,6 +16,7 @@u32 get_nr_cpus (void );u32 get_cpu_rev (void ); +u32 get_cpu_speed_grade_hz (void );/* returns MXC_CPU_ value */ #define cpu_type (rev) (((rev) >> 12)&0xff)
Signature · 1 line
1.9.1
PATCH v2 1/2 imx: mx6: add get_cpu_speed_grade_hz func to return MHz speed grade from OTP
Hi
2015-05-14 7:08 GMT+02:00 Tim Harvey <[email protected]>:
Quoted 24 lines
The IMX6 has four different speed grades determined by eFUSE
SPEED_GRADINGindicated by OCOTP_CFG3[17:16] which is at0x440in 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 <[email protected]>--- arch/arm/cpu/armv7/mx6/soc.c | 41 +++++++++++++++++++++++++++++++ arch/arm/include/asm/arch-mx6/sys_proto.h | 1 + 2 files changed, 42 insertions(+)arch/arm/cpu/armv7/mx6/soc.c +0
-0@@ -83,6 +83,47 @@ u32 get_cpu_rev(void)return (type <<12 ) | (reg +0x10 ); }
arch/arm/cpu/armv7/mx6/soc.c u32 get_cpu_rev(void) · line 94
Quoted 10 lines
arch/arm/cpu/armv7/mx6/soc.c +9
-0+/* +* 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).
Quoted 20 lines
arch/arm/cpu/armv7/mx6/soc.c +20
-0+ +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 :
arch/arm/cpu/armv7/mx6/soc.c u32 get_cpu_rev(void) · line 124
Quoted 10 lines
arch/arm/cpu/armv7/mx6/soc.c +10
-0+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.
greets
--
Christian Gmeiner, MSc
PATCH v2 1/2 imx: mx6: add get_cpu_speed_grade_hz func to return MHz speed grade from OTP
Hi Christian,
Quoted 28 lines · Christian Gmeiner
Hi
2015-05-14 7:08 GMT+02:00 Tim Harvey <[email protected]>:
Quoted 25 lines
The IMX6 has four different speed grades determined by eFUSE
SPEED_GRADINGindicated by OCOTP_CFG3[17:16] which is at0x440in 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 <[email protected]>--- arch/arm/cpu/armv7/mx6/soc.c | 41 +++++++++++++++++++++++++++++++ arch/arm/include/asm/arch-mx6/sys_proto.h | 1 + 2 files changed, 42 insertions(+)arch/arm/cpu/armv7/mx6/soc.c +0
-0@@ -83,6 +83,47 @@ u32 get_cpu_rev(void)return (type <<12 ) | (reg +0x10 ); }
Quoted 12 lines
arch/arm/cpu/armv7/mx6/soc.c u32 get_cpu_rev(void) · line 94
Quoted 9 lines
arch/arm/cpu/armv7/mx6/soc.c +9
-0+/* +* 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 3Note:
0x3is defined as reserved (IMX6DQRM Rev 2, 06/2014).
That means that the manual is buggy, if the SOC returns exactly this value ;-)
Quoted 27 lines
Quoted 27 lines
arch/arm/cpu/armv7/mx6/soc.c +27
-0+ +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 :
Quoted 8 lines
arch/arm/cpu/armv7/mx6/soc.c u32 get_cpu_rev(void) · line 124
Quoted 3 lines
arch/arm/cpu/armv7/mx6/soc.c +3
-0+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 theis_cpu_type(..)thing.
Function does not returns the value of the fuse, else it should returns val. The value is parsed for consistency, and if it is not, 0 means a failure. IMHO this interpretation is correct - I would agree with you only if the return value would be the read value, but it is not.
Best regards,
Stefano Babic
Quoted 7 lines
greets
--
Christian Gmeiner, MSc
Signature · 5 lines
===================================================================== DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de =====================================================================
PATCH v2 1/2 imx: mx6: add get_cpu_speed_grade_hz func to return MHz speed grade from OTP
2015-05-15 15:20 GMT+02:00 Stefano Babic <[email protected]>:
Quoted 44 lines
Hi Christian,
Quoted 28 lines · Christian Gmeiner
Hi
2015-05-14 7:08 GMT+02:00 Tim Harvey <[email protected]>:
Quoted 25 lines
The IMX6 has four different speed grades determined by eFUSE
SPEED_GRADINGindicated by OCOTP_CFG3[17:16] which is at0x440in 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 <[email protected]>--- arch/arm/cpu/armv7/mx6/soc.c | 41 +++++++++++++++++++++++++++++++ arch/arm/include/asm/arch-mx6/sys_proto.h | 1 + 2 files changed, 42 insertions(+)arch/arm/cpu/armv7/mx6/soc.c +0
-0@@ -83,6 +83,47 @@ u32 get_cpu_rev(void)return (type <<12 ) | (reg +0x10 ); }Quoted 12 lines
arch/arm/cpu/armv7/mx6/soc.c u32 get_cpu_rev(void) · line 94
Quoted 9 lines
arch/arm/cpu/armv7/mx6/soc.c +9
-0+/* +* 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 3Note:
0x3is defined as reserved (IMX6DQRM Rev 2, 06/2014).
Quoted 2 lines
That means that the manual is buggy, if the SOC returns exactly this value ;-)
yep :)
Quoted 37 lines
Quoted 28 lines
Quoted 28 lines
arch/arm/cpu/armv7/mx6/soc.c +27
-0+ +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 :Quoted 8 lines
arch/arm/cpu/armv7/mx6/soc.c u32 get_cpu_rev(void) · line 124
Quoted 3 lines
arch/arm/cpu/armv7/mx6/soc.c +3
-0+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 theis_cpu_type(..)thing.
Quoted 5 lines
Function does not returns the value of the fuse, else it should returns val. The value is parsed for consistency, and if it is not, 0 means a failure. IMHO this interpretation is correct - I would agree with you only if the return value would be the read value, but it is not.
If all mx6 variants use the same otp register/values, then the ifs are _NOT_ needed. I hope that later testings/doc updates/etc proofs it and we can get rid of the superfluous ifs.
If they are different then I can life with it.
greets
--
Christian Gmeiner, MSc
PATCH v2 1/2 imx: mx6: add get_cpu_speed_grade_hz func to return MHz speed grade from OTP
Hi Christian,
Quoted 10 lines · Christian Gmeiner
Quoted 5 lines
Function does not returns the value of the fuse, else it should returns val. The value is parsed for consistency, and if it is not, 0 means a failure. IMHO this interpretation is correct - I would agree with you only if the return value would be the read value, but it is not.
If all mx6 variants use the same otp register/values, then the ifs are _NOT_ needed. I hope that later testings/doc updates/etc proofs it and we can get rid of the superfluous ifs.
Ok - let's see if this can be proofed. It looks like we have to test and ask the hardware for that instead of relying on the documentation.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de =====================================================================
PATCH v2 1/2 imx: mx6: add get_cpu_speed_grade_hz func to return MHz speed grade from OTP
Quoted 15 lines · Stefano Babic
Hi Christian,
Quoted 10 lines · Christian Gmeiner
Quoted 5 lines
Function does not returns the value of the fuse, else it should returns val. The value is parsed for consistency, and if it is not, 0 means a failure. IMHO this interpretation is correct - I would agree with you only if the return value would be the read value, but it is not.
If all mx6 variants use the same otp register/values, then the ifs are _NOT_ needed. I hope that later testings/doc updates/etc proofs it and we can get rid of the superfluous ifs.
Quoted 6 lines
Ok - let's see if this can be proofed. It looks like we have to test and ask the hardware for that instead of relying on the documentation.
Best regards,
Stefano Babic
On our imx6sx board the patch outputs
U-Boot 2015.04-00074-g1bd6819 (May 15 2015 - 12:44:22)
CPU: Freescale i.MX6SX rev1.0 996 MHz (running at 792 MHz)
Reset cause: WDOG
Board: Nitrogen6sx
______________
Did you want me to test some variation of this?
Thanks
Troy
PATCH v2 1/2 imx: mx6: add get_cpu_speed_grade_hz func to return MHz speed grade from OTP
Quoted 33 lines · Troy Kisky
Quoted 15 lines · Stefano Babic
Hi Christian,
Quoted 10 lines · Christian Gmeiner
Quoted 5 lines
Function does not returns the value of the fuse, else it should returns val. The value is parsed for consistency, and if it is not, 0 means a failure. IMHO this interpretation is correct - I would agree with you only if the return value would be the read value, but it is not.
If all mx6 variants use the same otp register/values, then the ifs are _NOT_ needed. I hope that later testings/doc updates/etc proofs it and we can get rid of the superfluous ifs.
Quoted 6 lines
Ok - let's see if this can be proofed. It looks like we have to test and ask the hardware for that instead of relying on the documentation.
Best regards,
Stefano BabicOn our imx6sx board the patch outputs
U-Boot 2015.04-00074-g1bd6819 (May 15 2015 - 12:44:22)
CPU: Freescale i.MX6SX rev1.0 996 MHz (running at 792 MHz)
Reset cause: WDOG
Board: Nitrogen6sx
______________
Quoted 4 lines
Did you want me to test some variation of this?
Thanks
Troy
Troy,
As far as the frequency grade goes if you know the actual part number is a 1GHz part then that looks good - thanks for the test!
Could you provide similar results for the thermal grade patch series as well? (you will need to enable imx6 thermal sensor and remove the if (!imx6sx) around the print).
Thanks!
Tim
PATCH v2 1/2 imx: mx6: add get_cpu_speed_grade_hz func to return MHz speed grade from OTP
Quoted 37 lines · Tim Harvey
Quoted 35 lines · Troy Kisky
Quoted 15 lines · Stefano Babic
Hi Christian,
Quoted 10 lines · Christian Gmeiner
Quoted 5 lines
Function does not returns the value of the fuse, else it should returns val. The value is parsed for consistency, and if it is not, 0 means a failure. IMHO this interpretation is correct - I would agree with you only if the return value would be the read value, but it is not.
If all mx6 variants use the same otp register/values, then the ifs are _NOT_ needed. I hope that later testings/doc updates/etc proofs it and we can get rid of the superfluous ifs.
Quoted 6 lines
Ok - let's see if this can be proofed. It looks like we have to test and ask the hardware for that instead of relying on the documentation.
Best regards,
Stefano BabicOn our imx6sx board the patch outputs
U-Boot 2015.04-00074-g1bd6819 (May 15 2015 - 12:44:22)
CPU: Freescale i.MX6SX rev1.0 996 MHz (running at 792 MHz)
Reset cause: WDOG
Board: Nitrogen6sx
______________Did you want me to test some variation of this?
Quoted 7 lines
Quoted 2 lines
Thanks
TroyTroy,
As far as the frequency grade goes if you know the actual part number is a 1GHz part then that looks good - thanks for the test!
Right, it is a 1GHz part.
Quoted 4 lines
Could you provide similar results for the thermal grade patch series as well? (you will need to enable imx6 thermal sensor and remove the if (!imx6sx) around the print).
Will do.
Quoted 5 lines
Thanks!
Tim
PATCH v2 1/2 imx: mx6: add get_cpu_speed_grade_hz func to return MHz speed grade from OTP
Quoted 46 lines · Troy Kisky
Quoted 37 lines · Tim Harvey
Quoted 35 lines · Troy Kisky
Quoted 15 lines · Stefano Babic
Hi Christian,
Quoted 10 lines · Christian Gmeiner
Quoted 5 lines
Function does not returns the value of the fuse, else it should returns val. The value is parsed for consistency, and if it is not, 0 means a failure. IMHO this interpretation is correct - I would agree with you only if the return value would be the read value, but it is not.
If all mx6 variants use the same otp register/values, then the ifs are _NOT_ needed. I hope that later testings/doc updates/etc proofs it and we can get rid of the superfluous ifs.
Quoted 6 lines
Ok - let's see if this can be proofed. It looks like we have to test and ask the hardware for that instead of relying on the documentation.
Best regards,
Stefano BabicOn our imx6sx board the patch outputs
U-Boot 2015.04-00074-g1bd6819 (May 15 2015 - 12:44:22)
CPU: Freescale i.MX6SX rev1.0 996 MHz (running at 792 MHz)
Reset cause: WDOG
Board: Nitrogen6sx
______________Did you want me to test some variation of this?
Quoted 7 lines
Quoted 2 lines
Thanks
TroyTroy,
As far as the frequency grade goes if you know the actual part number is a 1GHz part then that looks good - thanks for the test!
Quoted 14 lines
Right, it is a 1GHz part.
Quoted 4 lines
Could you provide similar results for the thermal grade patch series as well? (you will need to enable imx6 thermal sensor and remove the if (!imx6sx) around the print).
Will do.
Quoted 5 lines
Thanks!
Tim
Ok. I think I gave bad info
The part number is PCIMX6X4AVM08AA, which should be -40 to 125 C, 800 MHz
and u-boot prints
U-Boot 2015.07-rc1-01048-gc4f95cb-dirty (May 15 2015 - 14:46:05)
CPU: Freescale i.MX6SX rev1.0 996 MHz (running at 792 MHz) CPU: Extended Commercial temperature grade (-20C to 105C)
_______________
U-boot then freezes in "uclass_get_device(UCLASS_THERMAL, 0, &thermal_dev);"
Troy
PATCH v2 1/2 imx: mx6: add get_cpu_speed_grade_hz func to return MHz speed grade from OTP
On Fri, May 15, 2015 at 7:34 PM, Troy Kisky
<[email protected]> wrote:
...
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
CPU: Freescale i.MX6SX rev1.0 996 MHz (running at 792 MHz)
...
TO1.0 is the first one and had some issues. We need testing with current production TO not alpha customers one.
Signature · 3 lines
Otavio Salvador O.S. Systems http://www.ossystems.com.br http://code.ossystems.com.br Mobile: +55 (53) 9981-7854 Mobile: +1 (347) 903-9750
PATCH v2 1/2 imx: mx6: add get_cpu_speed_grade_hz func to return MHz speed grade from OTP
Quoted 9 lines · Otavio Salvador
On Fri, May 15, 2015 at 7:34 PM, Troy Kisky
<[email protected]> wrote:
...Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
CPU: Freescale i.MX6SX rev1.0 996 MHz (running at 792 MHz)
...
TO1.0 is the first one and had some issues. We need testing with current production TO not alpha customers one.
Thanks for pointing that out, Otavio.
Troy
PATCH v2 1/2 imx: mx6: add get_cpu_speed_grade_hz func to return MHz speed grade from OTP
In reply to Christian GmeinerQuoted 28 lines · Christian Gmeiner
Hi
2015-05-14 7:08 GMT+02:00 Tim Harvey <[email protected]>:
Quoted 25 lines
The IMX6 has four different speed grades determined by eFUSE
SPEED_GRADINGindicated by OCOTP_CFG3[17:16] which is at0x440in 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 <[email protected]>--- arch/arm/cpu/armv7/mx6/soc.c | 41 +++++++++++++++++++++++++++++++ arch/arm/include/asm/arch-mx6/sys_proto.h | 1 + 2 files changed, 42 insertions(+)arch/arm/cpu/armv7/mx6/soc.c +0
-0@@ -83,6 +83,47 @@ u32 get_cpu_rev(void)return (type <<12 ) | (reg +0x10 ); }
Quoted 11 lines
arch/arm/cpu/armv7/mx6/soc.c u32 get_cpu_rev(void) · line 94
Quoted 9 lines
arch/arm/cpu/armv7/mx6/soc.c +9
-0+/* +* 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 3Note:
0x3is 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.
Quoted 28 lines
Quoted 28 lines
arch/arm/cpu/armv7/mx6/soc.c +27
-0+ +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 :
Quoted 8 lines
arch/arm/cpu/armv7/mx6/soc.c u32 get_cpu_rev(void) · line 124
Quoted 3 lines
arch/arm/cpu/armv7/mx6/soc.c +3
-0+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 theis_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
PATCH v2 1/2 imx: mx6: add get_cpu_speed_grade_hz func to return MHz speed grade from OTP
In reply to Tim HarveyHi Tim,
Quoted 75 lines · Tim Harvey
The IMX6 has four different speed grades determined by eFUSE
SPEED_GRADINGindicated by OCOTP_CFG3[17:16] which is at0x440in 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 <[email protected]>--- arch/arm/cpu/armv7/mx6/soc.c | 41 +++++++++++++++++++++++++++++++ arch/arm/include/asm/arch-mx6/sys_proto.h | 1 + 2 files changed, 42 insertions(+)arch/arm/cpu/armv7/mx6/soc.c +41
-0@@ -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 + +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 ; +} +#ifdef CONFIG_REVISION_TAG u32 __weak get_board_rev (void ) {arch/arm/include/asm/arch-mx6/sys_proto.h +0
-0
arch/arm/include/asm/arch-mx6/sys_proto.h line 22
Quoted 7 lines
arch/arm/include/asm/arch-mx6/sys_proto.h +1
-0@@ -16,6 +16,7 @@u32 get_nr_cpus (void );u32 get_cpu_rev (void ); +u32 get_cpu_speed_grade_hz (void );/* returns MXC_CPU_ value */ #define cpu_type (rev) (((rev) >> 12)&0xff)
U-Boot 2015.07-rc1-21804-gaf1db4a-dirty (May 18 2015 - 00:31:26)
CPU: Freescale i.MX6SOLO rev1.1 996 MHz (running at 792 MHz)
Reset cause: WDOG
Board: RIoTboard
Regards,
Nikolay
PATCH v2 2/2 mx: mx6: display max cpu frequency in print_cpuinfo()
In reply to Tim HarveyDisplay the max CPU frequency as well as the current running CPU frequency if the max CPU frequency is available and differs from the current CPU frequency.
Before:
CPU: Freescale i.MX6Q rev1.2 at 792 MHz
After - using an 800MHz IMX6DL (running at its max)
CPU: Freescale i.MX6DL rev1.1 at 792 MHz
After - using a 1GHz IMX6Q (not running at its max):
CPU: Freescale i.MX6Q rev1.2 996 MHz (running at 792 MHz)
---
v2:
- split out from patch that obtains the max cpu freq
- add before/after example and more description of change
--- arch/arm/imx-common/cpu.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
arch/arm/imx-common/cpu.c +15 -1
@@ -142,7 +142,7 @@ const char *get_imx_type(u32 imxtype)int print_cpuinfo (void ) { -u32 cpurev; +u32 cpurev, max_freq;#if defined(CONFIG_MX6 ) && defined(CONFIG_IMX6_THERMAL )struct udevice *thermal_dev;
@@ -151,11 +151,25 @@ int print_cpuinfo(void) cpurev =get_cpu_rev (); +#if defined(CONFIG_MX6 ) +printf ("CPU: Freescale i.MX%s rev%d.%d" , +get_imx_type ((cpurev &0xFF000 ) >>12 ), + (cpurev &0x000F0 ) >>4 , + (cpurev &0x0000F ) >>0 ); + max_freq =get_cpu_speed_grade_hz (); +if (!max_freq || max_freq ==mxc_get_clock (MXC_ARM_CLK )) { +printf (" at %dMHz\n" ,mxc_get_clock (MXC_ARM_CLK ) /1000000 ); + }else { +printf (" %d MHz (running at %d MHz)\n" , max_freq /1000000 , +mxc_get_clock (MXC_ARM_CLK ) /1000000 ); + } +#else printf ("CPU: Freescale i.MX%s rev%d.%d at %d MHz\n" ,get_imx_type ((cpurev &0xFF000 ) >>12 ), (cpurev &0x000F0 ) >>4 , (cpurev &0x0000F ) >>0 ,mxc_get_clock (MXC_ARM_CLK ) /1000000 ); +#endif #if defined(CONFIG_MX6 ) && defined(CONFIG_IMX6_THERMAL ) ret =uclass_get_device (UCLASS_THERMAL ,0 , &thermal_dev);
Signature · 1 line
1.9.1
PATCH v2 2/2 mx: mx6: display max cpu frequency in print_cpuinfo()
Quoted 54 lines · Tim Harvey
Display the max CPU frequency as well as the current running CPU frequency if the max CPU frequency is available and differs from the current CPU frequency.
Before:
CPU: Freescale i.MX6Q rev1.2 at 792 MHzAfter - using an 800MHz IMX6DL (running at its max)
CPU: Freescale i.MX6DL rev1.1 at 792 MHzAfter - using a 1GHz IMX6Q (not running at its max):
CPU: Freescale i.MX6Q rev1.2 996 MHz (running at 792 MHz)Signed-off-by Tim Harvey <[email protected]>---
v2:
- split out from patch that obtains the max cpu freq
- add before/after example and more description of changeSigned-off-by Tim Harvey <[email protected]>--- arch/arm/imx-common/cpu.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)arch/arm/imx-common/cpu.c +13
-1@@ -142,7 +142,7 @@ const char *get_imx_type(u32 imxtype)int print_cpuinfo (void ) { -u32 cpurev; +u32 cpurev, max_freq;#if defined(CONFIG_MX6 ) && defined(CONFIG_IMX6_THERMAL )struct udevice *thermal_dev;@@ -151,11 +151,25 @@ int print_cpuinfo(void) cpurev =get_cpu_rev (); +#if defined(CONFIG_MX6 ) +printf ("CPU: Freescale i.MX%s rev%d.%d" , +get_imx_type ((cpurev &0xFF000 ) >>12 ), + (cpurev &0x000F0 ) >>4 , + (cpurev &0x0000F ) >>0 ); + max_freq =get_cpu_speed_grade_hz (); +if (!max_freq || max_freq ==mxc_get_clock (MXC_ARM_CLK )) { +printf (" at %dMHz\n" ,mxc_get_clock (MXC_ARM_CLK ) /1000000 ); + }else { +printf (" %d MHz (running at %d MHz)\n" , max_freq /1000000 , +mxc_get_clock (MXC_ARM_CLK ) /1000000 ); + }
arch/arm/imx-common/cpu.c int print_cpuinfo(void) · line 175
Quoted 10 lines
arch/arm/imx-common/cpu.c +2
-0+#else printf ("CPU: Freescale i.MX%s rev%d.%d at %d MHz\n" ,get_imx_type ((cpurev &0xFF000 ) >>12 ), (cpurev &0x000F0 ) >>4 , (cpurev &0x0000F ) >>0 ,mxc_get_clock (MXC_ARM_CLK ) /1000000 ); +#endif #if defined(CONFIG_MX6 ) && defined(CONFIG_IMX6_THERMAL ) ret =uclass_get_device (UCLASS_THERMAL ,0 , &thermal_dev);
Regards,
Nikolay