X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=drivers%2Fthermal%2Fimx_thermal.c;h=de9aaf80d5498fa4bdee18b1a4f86d7839f44d05;hb=a83c6285388b5aa22980d96a70fff7d111d971fd;hp=116158511dba7928115a6d5f1ddda22d3cd4a122;hpb=878cd63e02f63f245182a101807186b44e20f116;p=karo-tx-uboot.git diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index 116158511d..de9aaf80d5 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -12,15 +12,15 @@ #include #include #include +#include #include #include #include #include #include -#define TEMPERATURE_MIN -40 -#define TEMPERATURE_HOT 80 -#define TEMPERATURE_MAX 125 +/* board will busyloop until this many degrees C below CPU max temperature */ +#define TEMPERATURE_HOT_DELTA 5 /* CPU maxT - 5C */ #define FACTOR0 10000000 #define FACTOR1 15976 #define FACTOR2 4297157 @@ -34,14 +34,21 @@ #define MISC0_REFTOP_SELBIASOFF (1 << 3) #define TEMPSENSE1_MEASURE_FREQ 0xffff +struct thermal_data { + unsigned int fuse; + int critical; + int minc; + int maxc; +}; + static int read_cpu_temperature(struct udevice *dev) { int temperature; unsigned int reg, n_meas; const struct imx_thermal_plat *pdata = dev_get_platdata(dev); - struct anatop_regs *anatop = (struct anatop_regs *)pdata->regs; - unsigned int *priv = dev_get_priv(dev); - u32 fuse = *priv; + struct anatop_regs *anatop = pdata->regs; + struct thermal_data *priv = dev_get_priv(dev); + u32 fuse = priv->fuse; int t1, n1; u32 c1, c2; u64 temp64; @@ -86,10 +93,7 @@ static int read_cpu_temperature(struct udevice *dev) writel(MISC0_REFTOP_SELBIASOFF, &anatop->ana_misc0_set); /* setup measure freq */ - reg = readl(&anatop->tempsense1); - reg &= ~TEMPSENSE1_MEASURE_FREQ; - reg |= MEASURE_FREQ; - writel(reg, &anatop->tempsense1); + writel(MEASURE_FREQ, &anatop->tempsense1); /* start the measurement process */ writel(TEMPSENSE0_MEASURE_TEMP, &anatop->tempsense0_clr); @@ -97,9 +101,16 @@ static int read_cpu_temperature(struct udevice *dev) writel(TEMPSENSE0_MEASURE_TEMP, &anatop->tempsense0_set); /* make sure that the latest temp is valid */ - while ((readl(&anatop->tempsense0) & - TEMPSENSE0_FINISHED) == 0) - udelay(10000); + const int max_loops = 30; + int loops = 0; + + while (((reg = readl(&anatop->tempsense0)) & TEMPSENSE0_FINISHED) == 0) { + udelay(5); + if (++loops >= max_loops) + break; + } + if ((readl(&anatop->tempsense0) & TEMPSENSE0_FINISHED) == 0) + return 0; /* read temperature count */ reg = readl(&anatop->tempsense0); @@ -108,7 +119,7 @@ static int read_cpu_temperature(struct udevice *dev) writel(TEMPSENSE0_FINISHED, &anatop->tempsense0_clr); /* milli_Tmeas = c2 - Nmeas * c1 */ - temperature = (c2 - n_meas * c1)/1000; + temperature = (long)(c2 - n_meas * c1) / 1000; /* power down anatop thermal sensor */ writel(TEMPSENSE0_POWER_DOWN, &anatop->tempsense0_set); @@ -119,18 +130,16 @@ static int read_cpu_temperature(struct udevice *dev) int imx_thermal_get_temp(struct udevice *dev, int *temp) { + struct thermal_data *priv = dev_get_priv(dev); int cpu_tmp = 0; cpu_tmp = read_cpu_temperature(dev); - while (cpu_tmp > TEMPERATURE_MIN && cpu_tmp < TEMPERATURE_MAX) { - if (cpu_tmp >= TEMPERATURE_HOT) { - printf("CPU Temperature is %d C, too hot to boot, waiting...\n", - cpu_tmp); - udelay(5000000); - cpu_tmp = read_cpu_temperature(dev); - } else { - break; - } + while (cpu_tmp >= priv->critical) { + printf("CPU Temperature (%dC) too close to max (%dC)", + cpu_tmp, priv->maxc); + puts(" waiting...\n"); + udelay(5000000); + cpu_tmp = read_cpu_temperature(dev); } *temp = cpu_tmp; @@ -144,23 +153,32 @@ static const struct dm_thermal_ops imx_thermal_ops = { static int imx_thermal_probe(struct udevice *dev) { + int ret; unsigned int fuse = ~0; - const struct imx_thermal_plat *pdata = dev_get_platdata(dev); - unsigned int *priv = dev_get_priv(dev); + struct thermal_data *priv = dev_get_priv(dev); /* Read Temperature calibration data fuse */ - fuse_read(pdata->fuse_bank, pdata->fuse_word, &fuse); + if ((ret = fuse_read(pdata->fuse_bank, pdata->fuse_word, &fuse))) { + printf("Failed to read temp calib fuse: %d\n", ret); + return ret; + } /* Check for valid fuse */ if (fuse == 0 || fuse == ~0) { - printf("CPU: Thermal invalid data, fuse: 0x%x\n", fuse); - return -EPERM; - } else { - printf("CPU: Thermal calibration data: 0x%x\n", fuse); + static int first = 1; + + if (first) { + printf("CPU: Thermal invalid data, fuse: %#10x\n", fuse); + first = 0; + } + return -EINVAL; } - *priv = fuse; + /* set critical cooling temp */ + get_cpu_temp_grade(&priv->minc, &priv->maxc); + priv->critical = priv->maxc - TEMPERATURE_HOT_DELTA; + priv->fuse = fuse; enable_thermal_clk(); @@ -172,6 +190,6 @@ U_BOOT_DRIVER(imx_thermal) = { .id = UCLASS_THERMAL, .ops = &imx_thermal_ops, .probe = imx_thermal_probe, - .priv_auto_alloc_size = sizeof(unsigned int), + .priv_auto_alloc_size = sizeof(struct thermal_data), .flags = DM_FLAG_PRE_RELOC, };