summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnson Huang <b20788@freescale.com>2011-12-22 16:59:39 +0800
committerAnson Huang <b20788@freescale.com>2011-12-22 18:30:47 +0800
commitfae9e8dcb136a12f8267102b1aa8f9df81d019ea (patch)
tree1f0b2a7eb5911d82a9c906e2ca80bb9baa347e0b
parent34e34f3ccb62a3fc51ba102c5cd87f4bcb625f4d (diff)
downloadu-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>
-rw-r--r--cpu/arm_cortexa8/mx6/generic.c103
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;
}