diff options
author | Anson Huang <b20788@freescale.com> | 2011-12-22 16:59:39 +0800 |
---|---|---|
committer | Anson Huang <b20788@freescale.com> | 2011-12-22 18:30:47 +0800 |
commit | fae9e8dcb136a12f8267102b1aa8f9df81d019ea (patch) | |
tree | 1f0b2a7eb5911d82a9c906e2ca80bb9baa347e0b /cpu | |
parent | 34e34f3ccb62a3fc51ba102c5cd87f4bcb625f4d (diff) | |
download | u-boot-imx-fae9e8dcb136a12f8267102b1aa8f9df81d019ea.zip u-boot-imx-fae9e8dcb136a12f8267102b1aa8f9df81d019ea.tar.gz u-boot-imx-fae9e8dcb136a12f8267102b1aa8f9df81d019ea.tar.bz2 |
ENGR00170837 [MX6]Add temperatuer check into uboot
We need to check CPU temperature in uboot, if cpu
is too hot, we will let it waiting there until cpu
temperature drop to save region, then go on boot
up.
Signed-off-by: Anson Huang <b20788@freescale.com>
Diffstat (limited to 'cpu')
-rw-r--r-- | cpu/arm_cortexa8/mx6/generic.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/cpu/arm_cortexa8/mx6/generic.c b/cpu/arm_cortexa8/mx6/generic.c index bf79613..7a42a5f 100644 --- a/cpu/arm_cortexa8/mx6/generic.c +++ b/cpu/arm_cortexa8/mx6/generic.c @@ -82,6 +82,14 @@ enum pll_clocks { #define NFC_CLK_MAX PLL2_FREQ_MAX #endif +#define OCOTP_THERMAL_OFFSET 0x4E0 +#define TEMPERATURE_MIN -25 +#define TEMPERATURE_HOT 80 +#define TEMPERATURE_MAX 125 +#define REG_VALUE_TO_CEL(ratio, raw) ((raw_n25c - raw) * 100 / ratio - 25) +static int cpu_tmp; +static unsigned int fuse; + #define SNVS_LPGPR_OFFSET 0x68 static u32 __decode_pll(enum pll_clocks pll, u32 infreq) @@ -792,6 +800,98 @@ int clk_config(u32 ref, u32 freq, u32 clk_type) } #endif +int read_cpu_temperature(void) +{ + unsigned int reg, tmp, temperature, i; + unsigned int raw_25c, raw_hot, hot_temp, raw_n25c, ratio; + unsigned int ccm_ccgr2; + + ccm_ccgr2 = readl(MXC_CCM_CCGR2); + writel(readl(MXC_CCM_CCGR2) | (0x3 << MXC_CCM_CCGR2_CG6_OFFSET), + MXC_CCM_CCGR2); + fuse = readl(OCOTP_BASE_ADDR + OCOTP_THERMAL_OFFSET); + writel(ccm_ccgr2, MXC_CCM_CCGR2); + if (fuse == 0 || fuse == 0xffffffff) + return TEMPERATURE_MIN; + + /* Fuse data layout: + * [31:20] sensor value @ 25C + * [19:8] sensor value of hot + * [7:0] hot temperature value */ + raw_25c = fuse >> 20; + raw_hot = (fuse & 0xfff00) >> 8; + hot_temp = fuse & 0xff; + + ratio = ((raw_25c - raw_hot) * 100) / (hot_temp - 25); + raw_n25c = raw_25c + ratio / 2; + + /* now we only using single measure, every time we measure + the temperature, we will power on/down the anadig module*/ + writel(BM_ANADIG_TEMPSENSE0_POWER_DOWN, + ANATOP_BASE_ADDR + HW_ANADIG_TEMPSENSE0_CLR); + writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, + ANATOP_BASE_ADDR + HW_ANADIG_ANA_MISC0_SET); + + /* write measure freq */ + reg = readl(ANATOP_BASE_ADDR + HW_ANADIG_TEMPSENSE1); + reg &= ~BM_ANADIG_TEMPSENSE1_MEASURE_FREQ; + reg |= 327; + writel(reg, ANATOP_BASE_ADDR + HW_ANADIG_TEMPSENSE1); + + writel(BM_ANADIG_TEMPSENSE0_MEASURE_TEMP, + ANATOP_BASE_ADDR + HW_ANADIG_TEMPSENSE0_CLR); + writel(BM_ANADIG_TEMPSENSE0_FINISHED, + ANATOP_BASE_ADDR + HW_ANADIG_TEMPSENSE0_CLR); + writel(BM_ANADIG_TEMPSENSE0_MEASURE_TEMP, + ANATOP_BASE_ADDR + HW_ANADIG_TEMPSENSE0_SET); + + tmp = 0; + /* read five times of temperature values to get average*/ + for (i = 0; i < 5; i++) { + while ((readl(ANATOP_BASE_ADDR + HW_ANADIG_TEMPSENSE0) + & BM_ANADIG_TEMPSENSE0_FINISHED) == 0) + udelay(10000); + reg = readl(ANATOP_BASE_ADDR + HW_ANADIG_TEMPSENSE0); + tmp += (reg & BM_ANADIG_TEMPSENSE0_TEMP_VALUE) + >> BP_ANADIG_TEMPSENSE0_TEMP_VALUE; + writel(BM_ANADIG_TEMPSENSE0_FINISHED, + ANATOP_BASE_ADDR + HW_ANADIG_TEMPSENSE0_CLR); + } + + tmp = tmp / 5; + if (tmp <= raw_n25c) + temperature = REG_VALUE_TO_CEL(ratio, tmp); + else + temperature = TEMPERATURE_MIN; + /* power down anatop thermal sensor */ + writel(BM_ANADIG_TEMPSENSE0_POWER_DOWN, + ANATOP_BASE_ADDR + HW_ANADIG_TEMPSENSE0_SET); + writel(BM_ANADIG_ANA_MISC0_REFTOP_SELBIASOFF, + ANATOP_BASE_ADDR + HW_ANADIG_ANA_MISC0_CLR); + + return temperature; + +} + +void check_cpu_temperature(void) +{ + cpu_tmp = read_cpu_temperature(); + while (cpu_tmp > TEMPERATURE_MIN && cpu_tmp < TEMPERATURE_MAX) { + if (cpu_tmp >= TEMPERATURE_HOT) { + printf("CPU is %d C, too hot to boot, waiting...\n", + cpu_tmp); + udelay(5000000); + cpu_tmp = read_cpu_temperature(); + } else + break; + } + if (cpu_tmp > TEMPERATURE_MIN && cpu_tmp < TEMPERATURE_MAX) + printf("Temperature: %d C, calibration data 0x%x\n", + cpu_tmp, fuse); + else + printf("Temperature: can't get valid data!\n"); +} + #if defined(CONFIG_DISPLAY_CPUINFO) int print_cpuinfo(void) { @@ -799,6 +899,9 @@ int print_cpuinfo(void) (get_board_rev() & 0xFF) >> 4, (get_board_rev() & 0xF), __get_mcu_main_clk() / SZ_DEC_1M); + + check_cpu_temperature(); + mxc_dump_clocks(); return 0; } |