Mnemoc,

have you checked and merged this yet?

Olliver

On 01/27/14 20:25, Patrick Wood wrote:
Enable the internal thermal monitoring support of AXP20X chips

Cherry-picked from:

https://github.com/cubieboard/linux-sunxi/commit/e4144b3ce62b1d7014fee36b84bc65c812469822

Creates the sysfs file temp1_input in the sunxi-i2c tree that reports the
AXP's temperature in degrees C.

According to the AXP202's datasheet, this port outputs a 12-bit value
where 0x000 == -144.7C and 0xfff == 264.8C in 0.1 degree C increments.

Signed-off-by: LABBE Corentin <clabbe.montj...@gmail.com>
Signed-off-by: Hans de Goede <hdego...@redhat.com>
Signed-off-by: Patrick Wood <patrickhw...@gmail.com>
---
  drivers/power/axp_power/Kconfig     |    5 ++
  drivers/power/axp_power/axp-mfd.c   |    7 +++
  drivers/power/axp_power/axp20-mfd.h |  112 +++++++++++++++++++++++++++++++++++
  include/linux/mfd/axp-mfd.h         |    7 +++
  4 files changed, 130 insertions(+)

diff --git a/drivers/power/axp_power/Kconfig b/drivers/power/axp_power/Kconfig
index 039679f..b76f517 100644
--- a/drivers/power/axp_power/Kconfig
+++ b/drivers/power/axp_power/Kconfig
@@ -36,4 +36,9 @@ config AXP_CHGCHANGE
        bool "AXP charging current set when suspend\resume\shutdown"
        default y

+config AXP_HWMON
+       depends on HWMON
+       bool "Enable the internal thermal monitoring support of AXP20X chips"
+       default y
+
  endif # !AW_AXP
diff --git a/drivers/power/axp_power/axp-mfd.c 
b/drivers/power/axp_power/axp-mfd.c
index 9af0257..cfa894a 100644
--- a/drivers/power/axp_power/axp-mfd.c
+++ b/drivers/power/axp_power/axp-mfd.c
@@ -363,6 +363,13 @@ static int __devexit axp_mfd_remove(struct i2c_client 
*client)
        pm_power_off = NULL;
        axp = NULL;

+#ifdef CONFIG_AXP_HWMON
+       if (chip->itm_enabled == 1) {
+               hwmon_device_unregister(chip->hwmon_dev);
+               sysfs_remove_group(&client->dev.kobj, &axp20_group);
+       }
+#endif
+
        axp_mfd_remove_subdevs(chip);
        kfree(chip);
        return 0;
diff --git a/drivers/power/axp_power/axp20-mfd.h 
b/drivers/power/axp_power/axp20-mfd.h
index 1c7a41b..214856e 100644
--- a/drivers/power/axp_power/axp20-mfd.h
+++ b/drivers/power/axp_power/axp20-mfd.h
@@ -22,6 +22,83 @@

  #include "axp-rw.h"

+#ifdef CONFIG_AXP_HWMON
+
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
+
+static struct axp_mfd_chip *axp20_update_device(struct device *dev);
+
+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 axp_mfd_chip *data = axp20_update_device(dev);
+       if (attr->index == 1)
+               return sprintf(buf, "264800\n");
+       if (attr->index == 2)
+               return sprintf(buf, "-144700\n");
+       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 struct attribute *axp20_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,
+       NULL
+};
+
+static const struct attribute_group axp20_group = {
+       .attrs = axp20_attributes,
+};
+
+
+/*
+ *  * function that update the status of the chips (temperature)
+ *   */
+static struct axp_mfd_chip *axp20_update_device(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct axp_mfd_chip *data = i2c_get_clientdata(client);
+       int err;
+       u8 high, low;
+
+       mutex_lock(&data->lock);
+
+       if (time_after(jiffies, data->last_updated + HZ * 2)
+               || !data->valid) {
+               dev_dbg(&client->dev, "Updating axp20 data\n");
+               /* AXP202 datasheet page 25, 0x000 means -144.7,
+                * 0xfff means 264.8, 4096 steps of 0.1 degress */
+               err = __axp_read(client, 0x5E, &high);
+               if (err) {
+                       dev_err(dev, "AXP Error while reading high\n");
+                       high = 0;
+               }
+
+               err = __axp_read(client, 0x5F, &low);
+               if (err) {
+                       dev_err(dev, "AXP Error while reading low\n");
+                       low = 0;
+               }
+
+               data->temperature = -1447 + ((high << 4) + (low && 0x0F));
+               data->last_updated = jiffies;
+               data->valid = 1;
+       }
+
+       mutex_unlock(&data->lock);
+       return data;
+}
+
+#endif
+

  static int __devinit axp20_init_chip(struct axp_mfd_chip *chip)
  {
@@ -33,6 +110,9 @@ static int __devinit axp20_init_chip(struct axp_mfd_chip 
*chip)
                POWER20_INTSTS3, 0xff, POWER20_INTSTS4, 0xff,
                POWER20_INTSTS5, 0xff };
        int err;
+#ifdef CONFIG_AXP_HWMON
+       u8 enabled;
+#endif
        /*read chip id*/
        err =  __axp_read(chip->client, POWER20_IC_TYPE, &chip_id);
        if (err) {
@@ -51,7 +131,39 @@ static int __devinit axp20_init_chip(struct axp_mfd_chip 
*chip)
        dev_info(chip->dev, "AXP (CHIP ID: 0x%02x) detected\n", chip_id);
        chip->type = AXP20;

+#ifdef CONFIG_AXP_HWMON
+       err = __axp_read(chip->client, 0x83, &enabled);
+       if (err) {
+               dev_info(chip->dev, "AXP Cannot get internal temperature monitoring 
status\n");
+               return err;
+       }
+       if ((enabled & 0x80) > 0) {
+               chip->itm_enabled = 1;
+               dev_info(chip->dev, "AXP internal temperature monitoring 
enabled\n");
+
+               /* Register sysfs hooks */
+               err = sysfs_create_group(&chip->client->dev.kobj, &axp20_group);
+               if (err)
+                       return err;
+
+               chip->hwmon_dev = hwmon_device_register(&chip->client->dev);
+               if (IS_ERR(chip->hwmon_dev)) {
+                       err = PTR_ERR(chip->hwmon_dev);
+                       goto exit_remove_files;
+               }
+       } else {
+               dev_info(chip->dev, "AXP internal temperature monitoring 
disabled\n");
+               /* TODO enable it ?*/
+               chip->itm_enabled = 0;
+       }
+#endif
+
        return 0;
+#ifdef CONFIG_AXP_HWMON
+exit_remove_files:
+       sysfs_remove_group(&chip->client->dev.kobj, &axp20_group);
+       return err;
+#endif
  }

  static int axp20_disable_irqs(struct axp_mfd_chip *chip, uint64_t irqs)
diff --git a/include/linux/mfd/axp-mfd.h b/include/linux/mfd/axp-mfd.h
index 2511473..6e6843d 100644
--- a/include/linux/mfd/axp-mfd.h
+++ b/include/linux/mfd/axp-mfd.h
@@ -131,6 +131,13 @@ struct axp_mfd_chip {
        struct work_struct      irq_work;

        struct blocking_notifier_head notifier_list;
+#ifdef CONFIG_AXP_HWMON
+       s16 temperature; /* range from -1447 to 2648 */
+       unsigned long last_updated;     /* in jiffies */
+       char valid;     /* zero until following fields are valid */
+       struct device *hwmon_dev;
+       char itm_enabled;
+#endif
  };

  struct axp_mfd_chip_ops {


--
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to