I'm going to estimate an i.MX6Q in a tiny blade-server environment and use SabreLite as a sample.
I build a custom monolithic Linux kernel without USB, Video, encoders, sound, etc. - just CPUFreq, Thermal, SATA and Network.
Is it possible (via software) to cut voltage and clocks from those "unnecessary" features of the SoC to save power and drop heat dissipation?
Solved! Go to Solution.
Hi, Serguei
The PU power is powered up by default when SOC boot up, but we turn it off in our uboot, and only turn it on in kernel when their is VPU or GPU driver needed. So, if you build out VPU&GPU module as well as using our uboot, then this PU power is off. You can also dump register value of 0x20c8140 for me, if bit8~15 are all 0, then it is off.
BTW, please close this question if you think it is answered, thanks in advanced!
Hi,
See below:
1. Disable PU power domain and PCIe power:
1079 /* Need to power down xPU in GPC before turn off PU LDO */
1080 val = readl(GPC_BASE_ADDR + GPC_PGC_GPU_PGCR_OFFSET);
1081 writel(val | 0x1, GPC_BASE_ADDR + GPC_PGC_GPU_PGCR_OFFSET);
1082
1083 val = readl(GPC_BASE_ADDR + GPC_CNTR_OFFSET);
1084 writel(val | 0x1, GPC_BASE_ADDR + GPC_CNTR_OFFSET);
1085 while (readl(GPC_BASE_ADDR + GPC_CNTR_OFFSET) & 0x1)
1086 ;
1087
1088 /* Increase the VDDSOC to 1.2V and disable VDDPU */
1089 val = REG_RD(ANATOP_BASE_ADDR, HW_ANADIG_REG_CORE);
1090 val &= ~BM_ANADIG_REG_CORE_REG2_TRG;
1091 val &= ~BM_ANADIG_REG_CORE_REG1_TRG;
1092 val |= BF_ANADIG_REG_CORE_REG2_TRG(0x14);
1093 REG_WR(ANATOP_BASE_ADDR, HW_ANADIG_REG_CORE, val);
1094
1095 /* Need to power down PCIe */
1096 val = REG_RD(IOMUXC_BASE_ADDR, IOMUXC_GPR1_OFFSET);
1097 val |= (0x1 << 18);
1098 REG_WR(IOMUXC_BASE_ADDR, IOMUXC_GPR1_OFFSET, val);
2. Disable module clock:
CCM_CCGR0~CCGR6, set those modules clock to 0.
Thanks, I find those code in arch_cpu_init().
Does it means, that PU is unpowered by default, so I do not need turn it off manually?
Hi, Serguei
The PU power is powered up by default when SOC boot up, but we turn it off in our uboot, and only turn it on in kernel when their is VPU or GPU driver needed. So, if you build out VPU&GPU module as well as using our uboot, then this PU power is off. You can also dump register value of 0x20c8140 for me, if bit8~15 are all 0, then it is off.
BTW, please close this question if you think it is answered, thanks in advanced!
how can I read those register?
doing something like int reg=__raw_readl(0x20c8140); from kernel module just makes panic.
You cannot read physical registers from the kernel that way.
There is a devregs program from here that you can use to probe the imx6 registers from user space (its for imx5 but applies to imx6 as well): http://boundarydevices.com/i-mx5x-device-register-access/
You may have to add the register definitions to the devregs_imx6x.dat file for the registers you want to access
devregs is not working as is, I get "Error reading CPU type". This is because it searches for "Revision" string in "/proc/cpuinfo".
Mine looks like the following:
processor : 0
model name : ARMv7 Processor rev 10 (v7l)
BogoMIPS : 790.52
Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls lpae
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x2
CPU part : 0xc09
CPU revision : 10
processor : 1
model name : ARMv7 Processor rev 10 (v7l)
BogoMIPS : 790.52
Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls lpae
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x2
CPU part : 0xc09
CPU revision : 10
processor : 2
model name : ARMv7 Processor rev 10 (v7l)
BogoMIPS : 790.52
Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls lpae
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x2
CPU part : 0xc09
CPU revision : 10
processor : 3
model name : ARMv7 Processor rev 10 (v7l)
BogoMIPS : 790.52
Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls lpae
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x2
CPU part : 0xc09
CPU revision : 10
Hardware : Freescale i.MX6 Quad/DualLite (Device Tree)
Revision : 0000
Serial : 0000000000000000
So I fix to search for "CPU revision". Though I get "unsupported CPU type: 10" it reads the register of interest!
The value is : 0x0050240a
Thus, bit8~15 are not zero...
If you moved over devregs_imx6x.dat from the git repo to /etc/devregs.dat on your sabrelite and added the necessary register address to this file, then the value that you are reading is correct. (getDataPath() function in devregs.cpp is returning /etc/devregs.dat filename for an unsupported cpu type)
Otherwise, the value that you are reading may not be correct. What OS are you running on the sabrelite? Most likely your proc/cpuinfo is not set up as expected (for the devregs program to read the cpu revision correctly). In any case, I think you have your answer as long as the steps above have been taken.
Linux 3.11.0-rc1
Yep, I move dat file to the proper location and add an entry for register 0x20c8140.
I try to write back a value 0x50000A (with cleared bits) to that register and see what is happen - nothing
The temperature stays at 50℃ in idle. What is pretty high, I think so.
According to the datasheet section 10.4.1.4.3.2, you also need to configure the PGC_GPU_CTRL (PGC Control Register - register 0x20DC260) to allow power down of the GPU/VPU platform. Bit 0 (Power Control) of this register must be set to '1' before you write to the 0x20c8140 register.
I get "Bus error" when reading 0x20DC260
According to section 27.8:PGC Memory Map/Register Definition of the datasheet, "Attempts to access registers when not in supervisor mode or attempts to access an unimplemented address location might trigger a bus transfer error". So this is what you may be seeing. So you will have to figure how to circumvent this. There is info in the datasheet on how to do this. As an alternate solution, I would recommend to not build GPU and VPU drivers in the kernel, just like AnsonHuang says. You can prevent these modules from building via menuconfig and then rebuild the kernel
As I mentioned above - I already build a monolithic kernel without GPU/VPU/CAAM (and others unnecessary) modules.
There is a series of power measurement scripts here:https://community.freescale.com/docs/DOC-93884
An alternate solution is to power off the VPU/GPU using Yongcai's code above at the end of the kernel boot sequence (presumably you will be in supervisory mode since you are still executing the kernel)
I can't read it from the kernel, and you say it is impossible.
Let's assume I'm turning off power, when clearing bits in 0x20c8140.
Should the temperature drop down?
Is it ok for this SoC to be 50℃ hot while idle (with 25℃ ambient)?
Probably AnsonHuang can help?
Yes, it is about ~40C on my board when idle. If you still get 50C, maybe you can check the all the CCM_CCGRx register, and turn off all unnecessary clocks, this could save many power and reduce the temperature. It would be great that if you can measure enable power rail, VDDARM_IN, VDDSOC_IN and VDDHIGH_IN, then compare it to our power application notes to see which rail is abnormal. Then maybe we can find some clues to lower the power consumption. Also, you can try different ODT setting of DDR3, it can save many power. The offset 0x818 of MMDC controller.
We can use weak ODT setting, it will save about 50% DDR
power in runtime. Now we use 0x00007
MMDC0_MPODTCTRL MMDC1_MPODTCTRL, (Ohm)
Setting DDR_ODT imx_ODT Max_overclocking
0x22227 120 060 615MHz
0x11117 120 120 604MHz
0x00007 120 000 576MHz
0x00000 000 000 556MHz
I found that I use u-boot from BoundaryDevices, which does not shutdown PU.
The latest u-boot from Freescale is not working for me - it can't initialize SATA. So I just add
imx_set_pcie_phy_power_down(); | |
imx_set_vddpu_power_down(); |
calls to arch_cpu_init(void).
Now the bits you mentioned are clear, but the temperature the same.
Maybe this is due to (high) voltage on CPU?
set_vddsoc(1200); | /* Set VDDSOC to 1.2V */ |
Is it safe to lower voltage here? Processor works max at 996Mhz.
Is it possible to look for current voltage, or measure. Should the voltage drop down, when CPUfreq lowering clock?
It should be not caused by the voltage, as in uboot the loading is very light. I think you should check the CCM_CCGRx, maybe there are too many clocks enabled. You should disable those modules' clock which are not necessary.
Do NOT lower the voltage, and yes, you can measure the voltage from the VDDARM_CAP/VDDSOC_CAP/VDDPU_CAP to get the output of LDO.
Yes, if CPUFreq is low, the voltage can be down. But in uboot, we run CPU at fixed clock of 792M. In kernel, the cpufreq driver will scale the freq/voltage accordingly. So there is no need to do any change to these voltage/freq.
My suggestion is to check the CCM_CCGRx's setting.
Yes, you can disable PU power which is supplying VPU and GPU. Please refer to Uboot, we have done that. For clock, you can gate those unnecessary clock in CCM ccgr register.