December 08, 2019, 07:36:08 pm

News:

Have you visited the Allwinner Chipset wiki? - http://linux-sunxi.org/


A20 Temperature Reading

Started by hds, May 06, 2014, 04:45:22 am

Previous topic - Next topic

hds

May 06, 2014, 04:45:22 am Last Edit: May 06, 2014, 05:47:51 am by hds
Reading Temperature of TP module inside the A20.
System: lubuntu 13.04
Linux cubietruck 3.4.79 #2 SMP PREEMPT Sat Feb 15 00:24:19 CST 2014 armv7l armv7l armv7l GNU/Linux

Ideas taken from Correntin Labbe (A20 SoC embedded touchscreen hwmon driver)
Needs: "sunxi_dbgreg" module.
--> /lib/modules/3.4.79/kernel/drivers/misc/sunxi-dbgreg.ko (on my system)
This module is a userland access possibility to access A20 registers.
When the module is loaded you can print a short readme: "cat /sys/devices/virtual/misc/sunxi-dbgreg/rw/read"


Getting the temperature:
1) sudo modprobe sunxi-dbgreg
2) check if driver created "read" and "write" under "/sys/devices/virtual/misc/sunxi-dbgreg/rw/"

3)
# For what the values mean, pls check Correntin Labbes c-prog.
# Preset the registers
echo 'f1c25000:27003f' > /sys/devices/virtual/misc/sunxi-dbgreg/rw/write;
echo 'f1c25010:40000' > /sys/devices/virtual/misc/sunxi-dbgreg/rw/write;
echo 'f1c25018:10fff' > /sys/devices/virtual/misc/sunxi-dbgreg/rw/write;
echo 'f1c25004:10' > /sys/devices/virtual/misc/sunxi-dbgreg/rw/write;
# read the Temperatur
echo 'f1c25020' > /sys/devices/virtual/misc/sunxi-dbgreg/rw/read;

4) If nothing jumped in between the last line in /var/log/syslog contains the hex value
   $ tail -n 1 /var/log/syslog
     "May  6 10:08:48 cubietruck kernel: [ 1766.866356] 0x72c"

5) Convert hex value
   echo "ibase=16; 72C" | bc --> 1836

6) Subtract 1447 and divide by 10:
   echo "scale=2; (1836-1447)/10" | bc --> 38.90 Degrees in Celcius

I needed to calibrate the 1447 to 1497. Checked the A20 output with a digital ir-thermometer.

Improvements:
a) Driver should print to device_file in "/sys/devices/virtual/misc/sunxi-dbgreg/rw/BlahBlah"
b) Output should include the requested address i.e. "f1c25020:0x72c"

Regards
Heiko


Attachement Kernel Driver and Correntin Labbes Code:
##########################################################################
# /* driver/misc/sunxi-dbgreg.c
#  *
#  *  Copyright (C) 2011 Allwinner Technology Co.Ltd
#  *  Tom Cubie <tangliang@allwinnertech.com>
#  *
#  *  www.allwinnertech.com
#  *
#  *  Read and write system registers in userspace.
#  *
#  * This program is free software; you can redistribute it and/or modify
#  * it under the terms of the GNU General Public License version 2 as
#  * published by the Free Software Foundation.
#  *
#  */

# #include <linux/module.h>
# #include <linux/init.h>
# #include <linux/pm.h>
# #include <linux/fs.h>
# #include <linux/io.h>
# #include <linux/kernel.h>
# #include <linux/slab.h>
# #include <linux/miscdevice.h>
# #include <linux/device.h>

# #undef DEBUG_SUNXI

# #ifdef DEBUG_SUNXI
# #define sunxi_reg_dbg(x...) printk(x)
# #else
# #define sunxi_reg_dbg(x...)
# #endif


# static char readme[] = "This is a userspace interface to access the sunxi soc registers.\n"
#                        "Usage:\n"
#                        "\techo address > read           # Read the value at address\n"
#                   "\teg: echo f1c20c14 > read\n"
#                        "\techo address:value > write    # Write value to address\n"
#                   "\teg: echo f1c20c14:ffff > write\n"
#                        "\tcat read or cat write         # See this readme\n"
#                        "Note: Always use hex and always use virtual address\n"
#                   "Warnning: use at your own risk\n";

# static ssize_t sunxi_debugreg_read_store(struct device *dev,
#             struct device_attribute *attr,
#             const char *buf, size_t count)
# {
#    unsigned long addr;
#    int err, len;

#    len = strlen(buf);

#    /* echo will append '\n', user may use 0x */
#    if( len != 9 && len != 11) {
#       printk("Invalid address length, please cat read to see readme\n");
#       return count;
#    }

#    err = strict_strtoul(buf, 16, &addr);

#    if (err) {
#       printk("Invalid value, please cat read to see readme\n");
#       return count;
#    }

#    if(addr < 0xf0000000) {
#       printk("Please use virtual address!!!\n");
#       return count;
#    }

#    printk("0x%x\n", readl(addr));

#    return count;
# }

# static ssize_t sunxi_debugreg_write_store(struct device *dev,
#             struct device_attribute *attr,
#             const char *buf, size_t count)
# {
#    unsigned long addr, value;
#    int err, len;
#    const char *s = NULL;
#    char addrstr[16];

#    s = strchr(buf, ':');
#    if( s == NULL) {
#       printk("Wrong format, no :, please cat write to see readme\n");
#       return count;
#    }

#    len = s - buf;
#    sunxi_reg_dbg("len: %d\n", len);

#    if( len != 8 && len != 10) {
#       printk("Invalid address length, please cat write to see readme\n");
#       return count;
#    }

#    strncpy(addrstr, buf, len);
#    addrstr[len] = '\0';

#    sunxi_reg_dbg("addrstr: %s\n", addrstr);

#    err = strict_strtoul(addrstr, 16, &addr);
#    sunxi_reg_dbg("addr: 0x%lx\n", addr);
#    if(err) {
#       printk("Invalid address, please cat write to see readme\n");
#       return count;
#    }

#    /* value starts after the : */
#    len = strlen(s+1);
#    sunxi_reg_dbg("s+1 length: %d\n", len);
#    if( len > 11) {
#       printk("Invalid value length, please cat read to see readme\n");
#       return count;
#    }

#    err = strict_strtoul(s+1, 16, &value);
#    sunxi_reg_dbg("value: 0x%lx\n", value);

#    if(err) {
#       printk("Invalid value, please cat write to see readme\n");
#       return count;
#    }

#    if(addr < 0xf0000000) {
#       printk("Please use virtual address!!!\n");
#       return count;
#    }

#    writel(value, addr);

#    return count;
# }

# static ssize_t sunxi_debugreg_show(struct device *dev,
#       struct device_attribute *attr, char *buf)
# {
#    return sprintf(buf, readme);
# }

# static DEVICE_ATTR(read, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
#       sunxi_debugreg_show, sunxi_debugreg_read_store);
# static DEVICE_ATTR(write, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH,
#       sunxi_debugreg_show, sunxi_debugreg_write_store);

# static struct attribute *sunxi_debugreg_attributes[] = {
#    &dev_attr_read.attr,
#    &dev_attr_write.attr,
#    NULL
# };

# static struct attribute_group sunxi_debugreg_attribute_group = {
#    .name = "rw",
#    .attrs = sunxi_debugreg_attributes
# };

# static struct miscdevice sunxi_debugreg_dev = {
#    .minor =   MISC_DYNAMIC_MINOR,
#    .name =      "sunxi-dbgreg",
# };

# static int __init sunxi_debugreg_init(void) {
#    int err;

#    pr_info("sunxi debug register driver init\n");

#    err = misc_register(&sunxi_debugreg_dev);
#    if(err) {
#       pr_err("%s register sunxi debug register driver as misc device error\n", __FUNCTION__);
#       goto exit;
#    }

#    err = sysfs_create_group(&sunxi_debugreg_dev.this_device->kobj,
#                    &sunxi_debugreg_attribute_group);

#    if(err) {
#       pr_err("%s create sysfs failed\n", __FUNCTION__);
#       goto exit;
#    }

# exit:
#    return err;
# }

# static void __exit sunxi_debugreg_exit(void) {

#    sunxi_reg_dbg("bye, sun4i_debugreg exit\n");
#    misc_deregister(&sunxi_debugreg_dev);
#    sysfs_remove_group(&sunxi_debugreg_dev.this_device->kobj,
#                    &sunxi_debugreg_attribute_group);
# }

# module_init(sunxi_debugreg_init);
# module_exit(sunxi_debugreg_exit);

# MODULE_DESCRIPTION("a simple sunxi debug driver");
# MODULE_AUTHOR("Tom Cubie");
# MODULE_LICENSE("GPL");


/*******************************************************/
/*******************************************************/
/*******************************************************/
/*******************************************************/
/*******************************************************/
/*******************************************************/


# Signed-off-by: LABBE Corentin <clabbe....@gmail.com>
# ---
# This driver exposes the temperature sensor found in the RTP of A20 SoC to the hwmon interface.
# Since I am only interested in getting the sensor value, I do not have patched the sun4i-ts driver.

# For the temperature value, I cannot found any document on how to transform the raw value in °C.
# Since the A20 and AXP209 chips are both produced by allwinner and in both case the hardware sensor is a 12 bit ADC,
# I have made the assumptions that the conversions rules are the same.
# With this conversions the temperature gived seems realistic.
# Under heavy loads, the temperature of both sensors rise linearly.

#  drivers/hwmon/Kconfig  |   9 ++
#  drivers/hwmon/Makefile |   1 +
#  drivers/hwmon/a20-tp.c | 271 +++++++++++++++++++++++++++++++++++++++++++++++++
#  3 files changed, 281 insertions(+)
#  create mode 100644 drivers/hwmon/a20-tp.c

# diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
# index 97f82e1..c9ff596 100644
# --- a/drivers/hwmon/Kconfig
# +++ b/drivers/hwmon/Kconfig
# @@ -48,6 +48,15 @@ config SENSORS_MMA7660
#            If you say yes here you get support for the Freescale 3-Axis
#            Orientation/Motion Detection Sensor.

# +config SENSORS_A20_TP_HWMON
# +        tristate "A20 SoC TP sensor controller"
# +        depends on !TOUCHSCREEN_SUN4I_TS
# +        help
# +          If you say yes here you get support for the hardware monitoring
# +          sensor present in the touch screen controler present on A20 SoC.
# +          This driver handle only this, if you want the full usage of the TP
# +          you need the other driver named sun4i-ts.
# +
#  config SENSORS_ABITUGURU
#          tristate "Abit uGuru (rev 1 & 2)"
#          depends on X86 && DMI && EXPERIMENTAL
# diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
# index a106b4c..68cef1b 100644
# --- a/drivers/hwmon/Makefile
# +++ b/drivers/hwmon/Makefile
# @@ -132,3 +132,4 @@ obj-$(CONFIG_PMBUS)                += pmbus/

#  ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG

# +obj-$(CONFIG_SENSORS_A20_TP_HWMON)                += a20-tp.o
# diff --git a/drivers/hwmon/a20-tp.c b/drivers/hwmon/a20-tp.c
# new file mode 100644
# index 0000000..78c2f08
# --- /dev/null
# +++ b/drivers/hwmon/a20-tp.c
# @@ -0,0 +1,271 @@
# +/*
# + * a20-tp.c - A20 SoC Resistive Touch Panel (RTP) embedded sensor driver only
# + *
# + * Copyright (C) 2013 Corentin LABBE <clabbe....@gmail.com>
# + *
# + * Datasheet: http://dl.linux-sunxi.org/A20/A20%20User%20Manual%202013-03-22.pdf
# + *
# + * This program is free software; you can redistribute it and/or modify
# + * it under the terms of the GNU General Public License as published by
# + * the Free Software Foundation version 2 of the License
# + *
# + * This program is distributed in the hope that it will be useful,
# + * but WITHOUT ANY WARRANTY; without even the implied warranty of
# + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# + * GNU General Public License for more details.
# + *
# + * You should have received a copy of the GNU General Public License
# + * along with this program; if not, write to the Free Software
# + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# + */
# +
# +#include <linux/hwmon-sysfs.h>
# +#include <linux/hwmon.h>
# +#include <linux/interrupt.h>
# +#include <linux/errno.h>
# +#include <linux/kernel.h>
# +#include <linux/module.h>
# +#include <linux/device.h>
# +#include <linux/platform_device.h>
# +#include <linux/init.h>
# +#include <linux/ioport.h>
# +#include <asm/irq.h>
# +#include <linux/io.h>
# +#include <linux/fs.h>
# +#include <linux/slab.h>
# +#include <mach/irqs.h>
# +#include <mach/system.h>
# +#include <mach/hardware.h>
# +
# +#define IRQ_TP                 29
# +#define TP_BASSADDRESS         0xf1c25000
# +#define TP_CTRL0               0x00
# +#define TP_CTRL1               0x04
# +#define TP_CTRL2               0x08
# +#define TP_CTRL3               0x0c
# +#define TP_INT_FIFOC           0x10
# +#define TP_INT_FIFOS           0x14
# +#define TP_TPR                 0x18
# +#define TP_CDAT                0x1c
# +#define TEMP_DATA              0x20
# +#define TP_DATA                0x24
# +
# +#define ADC_CLK_DIVIDER        (0x2<<20)
# +#define CLK                    7
# +#define FS_DIV                 (CLK<<16)
# +#define ACQ                    0x3f
# +#define T_ACQ                  ACQ
# +
# +#define TP_CTRL_MODE_EN        (1<<4)
# +
# +#define TP_DATA_IRQ_EN         (1<<16)
# +#define TP_FIFO_FLUSH          (1<<4)
# +#define TP_TEMP_IRQ_EN         (1<<18)
# +#define TP_TEMP_IRQ_PENDING    (1<<18)
# +
# +#define FIFO_DATA_PENDING      (1<<16)
# +#define TP_UP_PENDING          (1<<1)
# +#define TP_DOWN_PENDING        (1<<0)
# +
# +#define TP_TPR_TEMP_ENABLE     (1<<16)
# +#define TP_TPR_TEMP_PERIOD     0x0fff
# +
# +#define TP_TEMP_NODATA         -666
# +
# +struct tp_data {
# +        struct resource *res;
# +        void __iomem *base_addr;
# +        int irq;
# +        s16 temperature;
# +        struct device *hwmon_dev;
# +};
# +
# +/* Since we need to wait for an irq to have the temperature, we cannot give
# + * temperature for a short period of time.
# + * So until we have a temperature we return -EAGAIN */
# +static ssize_t
# +show_temp(struct device *dev, struct device_attribute *devattr, char *buf)
# +{
# +        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
# +        struct tp_data *data = dev_get_drvdata(dev);
# +        if (attr->index == 1)
# +                return sprintf(buf, "264800\n");
# +        if (attr->index == 2)
# +                return sprintf(buf, "-144700\n");
# +        if (attr->index == 3)
# +                return sprintf(buf, "a20_tp\n");
# +        if (data->temperature == TP_TEMP_NODATA)
# +                return -EAGAIN;
# +        return sprintf(buf, "%d\n", data->temperature * 100);
# +}
# +
# +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
# +static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, 1);
# +static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp, NULL, 2);
# +static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_temp, NULL, 3);
# +
# +static struct attribute *tp_attributes[] = {
# +        &sensor_dev_attr_temp1_input.dev_attr.attr,
# +        &sensor_dev_attr_temp1_min.dev_attr.attr,
# +        &sensor_dev_attr_temp1_max.dev_attr.attr,
# +        &sensor_dev_attr_name.dev_attr.attr,
# +        NULL
# +};
# +
# +static const struct attribute_group tp_group = {
# +        .attrs = tp_attributes,
# +};
# +
# +static irqreturn_t tp_handle_irq(int irq, void *dev_id)
# +{
# +        struct platform_device *pdev = dev_id;
# +        struct tp_data *ts_data = (struct tp_data *)platform_get_drvdata(pdev);
# +        unsigned int reg_val;
# +
# +        reg_val = readl(TP_BASSADDRESS + TP_INT_FIFOS);
# +        if (!(reg_val & (TP_DOWN_PENDING | FIFO_DATA_PENDING | TP_UP_PENDING))) {
# +                if (reg_val & TP_TEMP_IRQ_PENDING) {
# +                        writel(reg_val & TP_TEMP_IRQ_PENDING, TP_BASSADDRESS + TP_INT_FIFOS);
# +
# +                        reg_val = readl(TP_BASSADDRESS + TEMP_DATA);
# +                        reg_val &= 0x00000FFF;/* 12 bit wide */
# +                        ts_data->temperature = reg_val - 1447;
# +                        return IRQ_HANDLED;
# +                }
# +                return IRQ_NONE;
# +        }
# +        writel(reg_val, TP_BASSADDRESS + TP_INT_FIFOS);
# +        return IRQ_HANDLED;
# +}
# +
# +static int __devinit a20_tp_hwmon_probe(struct platform_device *pdev)
# +{
# +        int err = 0;
# +        int irq = platform_get_irq(pdev, 0);
# +        struct tp_data *ts_data;
# +
# +        ts_data = kzalloc(sizeof(struct tp_data), GFP_KERNEL);
# +        if (!ts_data) {
# +                dev_err(&pdev->dev, "Cannot allocate driver structures\n");
# +                err = -ENOMEM;
# +                return err;
# +        }
# +
# +        ts_data->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
# +        if (!ts_data->res) {
# +                err = -ENOMEM;
# +                dev_err(&pdev->dev, "Cannot get the MEMORY\n");
# +                goto label_err1;
# +        }
# +
# +        ts_data->base_addr = (void __iomem *)TP_BASSADDRESS;
# +
# +        ts_data->irq = irq;
# +
# +        err = request_irq(irq, tp_handle_irq,
# +                        IRQF_DISABLED, pdev->name, pdev);
# +        if (err) {
# +                dev_err(&pdev->dev, "Cannot request keypad IRQ\n");
# +                goto label_err1;
# +        }
# +
# +        platform_set_drvdata(pdev, ts_data);
# +
# +        ts_data->temperature = TP_TEMP_NODATA;
# +
# +        writel(ADC_CLK_DIVIDER | FS_DIV | T_ACQ, TP_BASSADDRESS + TP_CTRL0);
# +
# +        /* Enable the temperature IRQ */
# +        writel(TP_TEMP_IRQ_EN, TP_BASSADDRESS + TP_INT_FIFOC);
# +
# +        /* Enable the temperature */
# +        writel(TP_TPR_TEMP_ENABLE | TP_TPR_TEMP_PERIOD, TP_BASSADDRESS + TP_TPR);
# +
# +        /* Enable TP */
# +        writel(TP_CTRL_MODE_EN, TP_BASSADDRESS + TP_CTRL1);
# +
# +        err = sysfs_create_group(&pdev->dev.kobj, &tp_group);
# +        if (err) {
# +                dev_err(&pdev->dev, "Cannot create sysfs group\n");
# +                goto label_err2;
# +        }
# +
# +        ts_data->hwmon_dev = hwmon_device_register(&pdev->dev);
# +        if (IS_ERR(ts_data->hwmon_dev)) {
# +                err = PTR_ERR(ts_data->hwmon_dev);
# +                goto label_err3;
# +        }
# +        dev_info(&pdev->dev, "TP initialization success\n");
# +        return 0;
# +label_err3:
# +        sysfs_remove_group(&pdev->dev.kobj, &tp_group);
# +label_err2:
# +        free_irq(ts_data->irq, pdev);
# +label_err1:
# +        kfree(ts_data);
# +        return err;
# +}
# +
# +static int __devexit a20_tp_hwmon_remove(struct platform_device *pdev)
# +{
# +        struct tp_data *ts_data = platform_get_drvdata(pdev);
# +
# +        /* desactivate all IRQ */
# +        writel(0, ts_data->base_addr + TP_INT_FIFOC);
# +
# +        hwmon_device_unregister(ts_data->hwmon_dev);
# +        sysfs_remove_group(&pdev->dev.kobj, &tp_group);
# +
# +        free_irq(ts_data->irq, pdev);
# +        kfree(ts_data);
# +        platform_set_drvdata(pdev, NULL);
# +        return 0;
# +}
# +
# +static struct platform_driver a20_tp_hwmon_driver = {
# +        .probe           = a20_tp_hwmon_probe,
# +        .remove          = __devexit_p(a20_tp_hwmon_remove),
# +        .driver          = {
# +                .name    = "a20-tp-hwmon",
# +        },
# +};
# +
# +static struct resource a20_tp_hwmon_resource[] = {
# +        {
# +                .flags  = IORESOURCE_IRQ,
# +                .start  = SW_INT_IRQNO_TOUCH_PANEL ,
# +                .end    = SW_INT_IRQNO_TOUCH_PANEL ,
# +        },
# +        {
# +                .flags  = IORESOURCE_MEM,
# +                .start  = TP_BASSADDRESS,
# +                .end    = TP_BASSADDRESS + 0x100-1,
# +        },
# +};
# +
# +struct platform_device a20_tp_hwmon_device = {
# +        .name            = "a20-tp-hwmon",
# +        .id              = -1,
# +        .resource        = a20_tp_hwmon_resource,
# +        .num_resources   = ARRAY_SIZE(a20_tp_hwmon_resource),
# +};
# +
# +static int __init a20_tp_hwmon_init(void)
# +{
# +        platform_device_register(&a20_tp_hwmon_device);
# +        return platform_driver_register(&a20_tp_hwmon_driver);
# +}
# +
# +static void __exit a20_tp_hwmon_exit(void)
# +{
# +        platform_driver_unregister(&a20_tp_hwmon_driver);
# +        platform_device_unregister(&a20_tp_hwmon_device);
# +}
# +
# +module_init(a20_tp_hwmon_init);
# +module_exit(a20_tp_hwmon_exit);
# +
# +MODULE_AUTHOR("Corentin LABBE");
# +MODULE_DESCRIPTION("A20 SoC embedded touchscreen hwmon driver");
# +MODULE_LICENSE("GPL");
# +
# --
# 1.8.1.5


tkaiser

Quote from: hds on May 06, 2014, 04:45:22 amecho 'f1c25004:10' > /sys/devices/virtual/misc/sunxi-dbgreg/rw/write;


In case you write \x10 you only set bit 4 and therefore clear bit 7. That's A20's CHOP_TEMP_EN register (according to the A20's user manual: "Chop temperature calibration enable: 0: Disable, 1: Enable")

I tried to read out the temperature values according to your method with another A20 based board and got completely different results when I attached a heatsink to the A20 (25° lower than before without the heatsink): http://forum.lemaker.org/forum.php?mod=redirect&goto=findpost&ptid=8137&pid=40817

So right now I try it again with bit 7 set to the default (1: Enable) using "echo 'f1c25004:90' > /sys/devices/virtual/misc/sunxi-dbgreg/rw/write;" and the temperatures reported look better.

I'm using this code with the aforementioned adjustement (\x90 instead of \x10 written to TP_CTRL1: http://pastebin.com/Rspxv4bx

Unfortunately I cannot measure on the A20's surface since I applied already the heatsink. Will have to double check with another A20 board (A20-OLinuXino-Lime2) and will report back.

But would be nice if you could look into it and whether I'm completely wrong...

hds

Looks like you are right. Probably my wrong because i just took over these values without checking what happnes to the registers.
Sending 0x10 or 0x90 gives me a diff of 0x20 in the reading.
That would explain why i had to "recalibrate" the calculus afterwards by decimal 50.

So the correct values *seems* to be:
....
echo 'f1c25004:90'
....
# Subtract 1447 and divide by 10:
echo "scale=2; ({your calculated reading}-1447)/10" | bc

Thanks for sharing tkaiser.
Regards
Heiko

tkaiser

Quote from: hds on November 07, 2014, 04:08:15 am
Sending 0x10 or 0x90 gives me a diff of 0x20 in the reading


I made further tests with 2 Banana Pi and will continue this weekend with an A20-OLinuXino-LIME2 and maybe my Cubietruck as well (see the forum link above). But it looks to me that it's really important to set bit 7 to 1 to enable calibration otherwise the values reported are sort of random depending on boundary conditions.

Anyway, thanks for your great initial work  :)

tkaiser

November 10, 2014, 02:32:02 am #5 Last Edit: November 11, 2014, 05:16:48 am by tkaiser
Quote from: hds on November 07, 2014, 04:08:15 am
So the correct values *seems* to be:
....
echo 'f1c25004:90'


Based on further tests I would agree. But it's also important to not trust these values too much and to focus more on the PMU's thermal sensor (and understand how temperature of this unit interacts with system load and stuff like charging or powering external USB peripherals).

I wrote a conclusion here: http://forum.lemaker.org/forum.php?mod=redirect&goto=findpost&ptid=8137&pid=42872

tkaiser

November 10, 2014, 05:49:08 am #6 Last Edit: November 14, 2014, 05:54:57 am by tkaiser
BTW: I put the whole stuff into two shell functions (bash/zsh compatible): http://pastebin.com/jNLfSS4U

If stored into /etc/profile.d/temp-stuff.sh for example then these two functions should be accessible from every login shell. And I added a conversion to Fahrenheit when called with f or F as only argument:
cubietruck:~ tk$ pmutemp
approx. 42.2°C

cubietruck:~ tk$ pmutemp f
approx. 107.6°F

tkaiser

And here's an approach using a normal C programm without the need of a loaded kernel module and writing/parsing syslog: http://forum.lemaker.org/forum.php?mod=redirect&goto=findpost&ptid=8137&pid=47437