From fe02c2c77fa7b29b1a073cc08ecea34af6d87fd2 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 31 Mar 2015 09:56:27 +0800 Subject: MLK-10774-30 imx:mx7 dm thermal driver support Add thermal driver for mx7 Signed-off-by: Peng Fan --- arch/arm/cpu/armv7/mx7/clock.c | 5 ++ arch/arm/cpu/armv7/mx7/soc.c | 123 ++++------------------------------ arch/arm/imx-common/cpu.c | 5 +- arch/arm/include/asm/arch-mx7/clock.h | 1 + drivers/thermal/imx_thermal.c | 85 +++++++++++++++++++++++ include/configs/mx7d_arm2.h | 1 + 6 files changed, 108 insertions(+), 112 deletions(-) diff --git a/arch/arm/cpu/armv7/mx7/clock.c b/arch/arm/cpu/armv7/mx7/clock.c index 96017d3..f8d17df 100644 --- a/arch/arm/cpu/armv7/mx7/clock.c +++ b/arch/arm/cpu/armv7/mx7/clock.c @@ -67,6 +67,11 @@ void enable_ocotp_clk(unsigned char enable) { clock_enable(CCGR_OCOTP, enable); } + +void enable_thermal_clk(void) +{ + enable_ocotp_clk(1); +} #endif void enable_usboh3_clk(unsigned char enable) diff --git a/arch/arm/cpu/armv7/mx7/soc.c b/arch/arm/cpu/armv7/mx7/soc.c index 829e30c..a9e351f 100644 --- a/arch/arm/cpu/armv7/mx7/soc.c +++ b/arch/arm/cpu/armv7/mx7/soc.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #ifdef CONFIG_FASTBOOT #ifdef CONFIG_ANDROID_RECOVERY #include @@ -25,19 +27,20 @@ #include #endif -#define TEMPERATURE_MIN -40 -#define TEMPERATURE_HOT 80 -#define TEMPERATURE_MAX 125 -#define FACTOR1 15976 -#define FACTOR2 4297157 -#define MEASURE_FREQ 327 - -#define REG_VALUE_TO_CEL(ratio, raw) \ - ((raw_n40c - raw) * 100 / ratio - 40) +struct src *src_reg = (struct src *)SRC_BASE_ADDR; -static unsigned int fuse = ~0; +#if defined(CONFIG_IMX_THERMAL) +static const struct imx_thermal_plat imx7_thermal_plat = { + .regs = (void *)ANATOP_BASE_ADDR, + .fuse_bank = 3, + .fuse_word = 3, +}; -struct src *src_reg = (struct src *)SRC_BASE_ADDR; +U_BOOT_DEVICE(imx7_thermal) = { + .name = "imx_thermal", + .platdata = &imx7_thermal_plat, +}; +#endif u32 get_cpu_rev(void) { @@ -63,104 +66,6 @@ u32 __weak get_board_rev(void) } #endif -static int read_cpu_temperature(void) -{ - int temperature; - unsigned int reg, tmp; - unsigned int raw_25c, raw_n40c, ratio; - struct mxc_ccm_anatop_reg *ccm_anatop = (struct mxc_ccm_anatop_reg *) - ANATOP_BASE_ADDR; - struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; - struct fuse_bank *bank = &ocotp->bank[3]; - struct fuse_bank3_regs *fuse_bank3 = - (struct fuse_bank3_regs *)bank->fuse_regs; - - enable_ocotp_clk(1); - fuse = readl(&fuse_bank3->ana1); - - if (fuse == 0 || fuse == 0xffffffff || (fuse & 0xfff00000) == 0) - 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; - - /* - * The universal equation for thermal sensor - * is slope = 0.4297157 - (0.0015976 * 25C fuse), - * here we convert them to integer to make them - * easy for counting, FACTOR1 is 15976, - * FACTOR2 is 4297157. Our ratio = -100 * slope - */ - ratio = ((FACTOR1 * raw_25c - FACTOR2) + 50000) / 100000; - - debug("Thermal sensor with ratio = %d\n", ratio); - - raw_n40c = raw_25c + (13 * ratio) / 20; - - /* - * now we only use single measure, every time we read - * the temperature, we will power on/down anadig thermal - * module - */ - writel(TEMPMON_HW_ANADIG_TEMPSENSE1_POWER_DOWN_MASK, &ccm_anatop->tempsense0_clr); - writel(PMU_REF_REFTOP_SELFBIASOFF_MASK, &ccm_anatop->ref_set); - - /* write measure freq */ - reg = readl(&ccm_anatop->tempsense1); - reg &= ~TEMPMON_HW_ANADIG_TEMPSENSE1_MEASURE_FREQ_MASK; - reg |= TEMPMON_HW_ANADIG_TEMPSENSE1_MEASURE_FREQ(MEASURE_FREQ); - writel(reg, &ccm_anatop->tempsense1); - - writel(TEMPMON_HW_ANADIG_TEMPSENSE1_MEASURE_TEMP_MASK, &ccm_anatop->tempsense1_clr); - writel(TEMPMON_HW_ANADIG_TEMPSENSE1_FINISHED_MASK, &ccm_anatop->tempsense1_clr); - writel(TEMPMON_HW_ANADIG_TEMPSENSE1_MEASURE_TEMP_MASK, &ccm_anatop->tempsense1_set); - - while ((readl(&ccm_anatop->tempsense1) & - TEMPMON_HW_ANADIG_TEMPSENSE1_FINISHED_MASK) == 0) - udelay(10000); - - reg = readl(&ccm_anatop->tempsense1); - tmp = (reg & TEMPMON_HW_ANADIG_TEMPSENSE1_TEMP_VALUE_MASK) - >> TEMPMON_HW_ANADIG_TEMPSENSE1_TEMP_VALUE_SHIFT; - writel(TEMPMON_HW_ANADIG_TEMPSENSE1_FINISHED_MASK, &ccm_anatop->tempsense1_clr); - - if (tmp <= raw_n40c) - temperature = REG_VALUE_TO_CEL(ratio, tmp); - else - temperature = TEMPERATURE_MIN; - /* power down anatop thermal sensor */ - writel(TEMPMON_HW_ANADIG_TEMPSENSE1_POWER_DOWN_MASK, &ccm_anatop->tempsense0_set); - writel(PMU_REF_REFTOP_SELFBIASOFF_MASK, &ccm_anatop->ref_clr); - - return temperature; -} - -void check_cpu_temperature(void) -{ - int cpu_tmp = 0; - - 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("CPU: Temperature %d C, calibration data: 0x%x\n", - cpu_tmp, fuse); - else - printf("CPU: Temperature: can't get valid data!\n"); -} - static void init_aips(void) { struct aipstz_regs *aips1, *aips2, *aips3; diff --git a/arch/arm/imx-common/cpu.c b/arch/arm/imx-common/cpu.c index 6e3e617..da2629a 100644 --- a/arch/arm/imx-common/cpu.c +++ b/arch/arm/imx-common/cpu.c @@ -168,7 +168,7 @@ int print_cpuinfo(void) (struct dbg_monitor_regs *)DEBUG_MONITOR_BASE_ADDR; #endif -#if defined(CONFIG_MX6) && defined(CONFIG_IMX6_THERMAL) +#if defined(CONFIG_IMX_THERMAL) struct udevice *thermal_dev; int cpu_tmp, ret; #endif @@ -181,8 +181,7 @@ int print_cpuinfo(void) (cpurev & 0x0000F) >> 0, mxc_get_clock(MXC_ARM_CLK) / 1000000); -#if (defined(CONFIG_MX6) && defined(CONFIG_IMX6_THERMAL)) || \ - (defined(CONFIG_MX7) && defined(CONFIG_IMX7_THERMAL)) +#if defined(CONFIG_IMX_THERMAL) ret = uclass_get_device(UCLASS_THERMAL, 0, &thermal_dev); if (!ret) { ret = thermal_get_temp(thermal_dev, &cpu_tmp); diff --git a/arch/arm/include/asm/arch-mx7/clock.h b/arch/arm/include/asm/arch-mx7/clock.h index cd128ce..290de9f 100644 --- a/arch/arm/include/asm/arch-mx7/clock.h +++ b/arch/arm/include/asm/arch-mx7/clock.h @@ -345,4 +345,5 @@ void hab_caam_clock_enable(void); void hab_caam_clock_disable(void); #endif void mxs_set_lcdclk(uint32_t base_addr, uint32_t freq); +void enable_thermal_clk(void); #endif diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index 4e1e412..cc355b3 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -18,6 +18,7 @@ #include #include +#if defined(CONFIG_MX6) #define TEMPERATURE_MIN -40 #define TEMPERATURE_HOT 80 #define TEMPERATURE_MAX 125 @@ -116,6 +117,78 @@ static int read_cpu_temperature(struct udevice *dev) return temperature; } +#elif defined(CONFIG_MX7) +#define TEMPERATURE_MIN -40 +#define TEMPERATURE_HOT 85 +#define TEMPERATURE_MAX 125 +#define MEASURE_FREQ 327 + +static int read_cpu_temperature(struct udevice *dev) +{ + unsigned int reg, tmp, start; + unsigned int raw_25c, te1; + int temperature; + unsigned int *priv = dev_get_priv(dev); + u32 fuse = *priv; + struct mxc_ccm_anatop_reg *ccm_anatop = (struct mxc_ccm_anatop_reg *) + ANATOP_BASE_ADDR; + /* + * fuse data layout: + * [31:21] sensor value @ 25C + * [20:18] hot temperature value + * [17:9] sensor value of room + * [8:0] sensor value of hot + */ + + raw_25c = fuse >> 21; + if (raw_25c == 0) + raw_25c = 25; + + te1 = (fuse >> 9) & 0x1ff; + + /* + * now we only use single measure, every time we read + * the temperature, we will power on/down anadig thermal + * module + */ + writel(TEMPMON_HW_ANADIG_TEMPSENSE1_POWER_DOWN_MASK, &ccm_anatop->tempsense1_clr); + writel(PMU_REF_REFTOP_SELFBIASOFF_MASK, &ccm_anatop->ref_set); + + /* write measure freq */ + reg = readl(&ccm_anatop->tempsense1); + reg &= ~TEMPMON_HW_ANADIG_TEMPSENSE1_MEASURE_FREQ_MASK; + reg |= TEMPMON_HW_ANADIG_TEMPSENSE1_MEASURE_FREQ(MEASURE_FREQ); + writel(reg, &ccm_anatop->tempsense1); + + writel(TEMPMON_HW_ANADIG_TEMPSENSE1_MEASURE_TEMP_MASK, &ccm_anatop->tempsense1_clr); + writel(TEMPMON_HW_ANADIG_TEMPSENSE1_FINISHED_MASK, &ccm_anatop->tempsense1_clr); + writel(TEMPMON_HW_ANADIG_TEMPSENSE1_MEASURE_TEMP_MASK, &ccm_anatop->tempsense1_set); + + start = get_timer(0); + /* Wait max 2s */ + do { + reg = readl(&ccm_anatop->tempsense1); + tmp = (reg & TEMPMON_HW_ANADIG_TEMPSENSE1_TEMP_VALUE_MASK) + >> TEMPMON_HW_ANADIG_TEMPSENSE1_TEMP_VALUE_SHIFT; + if (tmp != 0) + break; + } while (get_timer(0) < (start + 2000)); + /* Still not get invalid temperature? */ + if (tmp == 0) + return -EINVAL; + + writel(TEMPMON_HW_ANADIG_TEMPSENSE1_FINISHED_MASK, &ccm_anatop->tempsense1_clr); + + /* Single point */ + temperature = tmp - (te1 - raw_25c); + + /* power down anatop thermal sensor */ + writel(TEMPMON_HW_ANADIG_TEMPSENSE1_POWER_DOWN_MASK, &ccm_anatop->tempsense1_set); + writel(PMU_REF_REFTOP_SELFBIASOFF_MASK, &ccm_anatop->ref_clr); + + return temperature; +} +#endif int imx_thermal_get_temp(struct udevice *dev, int *temp) { @@ -152,11 +225,23 @@ static int imx_thermal_probe(struct udevice *dev) /* Read Temperature calibration data fuse */ fuse_read(pdata->fuse_bank, pdata->fuse_word, &fuse); +#if defined(CONFIG_MX6) /* Check for valid fuse */ if (fuse == 0 || fuse == ~0 || (fuse & 0xfff00000) == 0) { printf("CPU: Thermal invalid data, fuse: 0x%x\n", fuse); return -EPERM; } +#elif defined(CONFIG_MX7) + /* No Calibration data in FUSE? */ + if ((fuse & 0x3ffff) == 0) + return -EPERM; + + /* We do not support 105C TE2 */ + if (((fuse & 0x1c0000) >> 18) == 0x6) + return -EPERM; +#else +#error "Not support thermal driver" +#endif *priv = fuse; diff --git a/include/configs/mx7d_arm2.h b/include/configs/mx7d_arm2.h index 06ff695..118e94c 100644 --- a/include/configs/mx7d_arm2.h +++ b/include/configs/mx7d_arm2.h @@ -42,6 +42,7 @@ #define CONFIG_MXC_UART #define CONFIG_MXC_UART_BASE UART1_IPS_BASE_ADDR +#define CONFIG_IMX_THERMAL #define CONFIG_CMD_FUSE #ifdef CONFIG_CMD_FUSE #define CONFIG_MXC_OCOTP -- cgit v1.1