[PATCH] hwmon: OMAP4460+: On die temperature sensor driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On chip temperature sensor driver. The driver monitors the temperature of
on die subsystems. It sends notifications to the user space if
the temperature crosses user defined thresholds via kobject_uevent interface.
The user is allowed to configure the temperature thresholds vis sysfs nodes
exposed using hwmon interface.

The patch depends on the the following series:
http://comments.gmane.org/gmane.linux.ports.arm.omap/64436
and
http://permalink.gmane.org/gmane.linux.ports.arm.omap/64446

Signed-off-by: Keerthy <j-keerthy@xxxxxx>
Cc: Jean Delvare <khali@xxxxxxxxxxxx>
Cc: Guenter Roeck <guenter.roeck@xxxxxxxxxxxx>
Cc: lm-sensors@xxxxxxxxxxxxxx
---
 Documentation/hwmon/omap_temp_sensor     |   25 +++
 drivers/hwmon/Kconfig                    |   11 ++
 drivers/hwmon/Makefile                   |    1 +
 drivers/hwmon/omap4460plus_temp_sensor.c |  244 ++++++++++++++++++++++++++++++
 4 files changed, 281 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/hwmon/omap_temp_sensor
 create mode 100644 drivers/hwmon/omap4460plus_temp_sensor.c

Index: linux-omap-2.6/Documentation/hwmon/omap_temp_sensor
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-omap-2.6/Documentation/hwmon/omap_temp_sensor	2011-09-22 18:57:23.180918857 +0530
@@ -0,0 +1,25 @@
+Kernel driver omap_temp_sensor
+==============================
+
+Supported chips:
+  * Texas Instruments OMAP4460
+    Prefix: 'omap_temp_sensor'
+
+Author:
+        J Keerthy <j-keerthy@xxxxxx>
+
+Description
+-----------
+
+The Texas Instruments OMAP4 family of chips have a bandgap temperature sensor.
+The temperature sensor feature is used to convert the temperature of the device
+into a decimal value coded on 10 bits. An internal ADC is used for conversion.
+The recommended operating temperatures must be in the range -40 degree Celsius
+to 123 degree celsius for standard conversion.
+The thresholds are programmable and upon crossing the thresholds an interrupt
+is generated. The OMAP temperature sensor has a programmable update rate in
+milli seconds.
+(Currently the driver programs a default of 2000 milliseconds).
+
+The driver provides the common sysfs-interface for temperatures (see
+Documentation/hwmon/sysfs-interface under Temperatures).
Index: linux-omap-2.6/drivers/hwmon/Kconfig
===================================================================
--- linux-omap-2.6.orig/drivers/hwmon/Kconfig	2011-09-22 17:48:38.032575702 +0530
+++ linux-omap-2.6/drivers/hwmon/Kconfig	2011-09-22 19:02:28.744575604 +0530
@@ -323,6 +323,17 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called f71805f.
 
+config SENSORS_OMAP_BANDGAP_TEMP_SENSOR
+	bool "OMAP on-die temperature sensor hwmon driver"
+	depends on HWMON && ARCH_OMAP && OMAP4460PLUS_SCM
+	help
+	  If you say yes here you get support for hardware
+	  monitoring features of the OMAP on die temperature
+	  sensor.
+
+	  Continuous conversion programmable delay
+	  mode is used for temperature conversion.
+
 config SENSORS_F71882FG
 	tristate "Fintek F71882FG and compatibles"
 	help
Index: linux-omap-2.6/drivers/hwmon/Makefile
===================================================================
--- linux-omap-2.6.orig/drivers/hwmon/Makefile	2011-09-22 17:48:38.020575728 +0530
+++ linux-omap-2.6/drivers/hwmon/Makefile	2011-09-22 18:57:23.192574712 +0530
@@ -93,6 +93,7 @@
 obj-$(CONFIG_SENSORS_MAX6642)	+= max6642.o
 obj-$(CONFIG_SENSORS_MAX6650)	+= max6650.o
 obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
+obj-$(CONFIG_SENSORS_OMAP_BANDGAP_TEMP_SENSOR)  += omap4460plus_temp_sensor.o
 obj-$(CONFIG_SENSORS_NTC_THERMISTOR)	+= ntc_thermistor.o
 obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
 obj-$(CONFIG_SENSORS_PC87427)	+= pc87427.o
Index: linux-omap-2.6/drivers/hwmon/omap4460plus_temp_sensor.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-omap-2.6/drivers/hwmon/omap4460plus_temp_sensor.c	2011-09-22 19:02:11.096575567 +0530
@@ -0,0 +1,242 @@
+/*
+ *
+ * OMAP4460 Plus bandgap on die sensor hwmon driver.
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * J Keerthy <j-keerthy@xxxxxx>
+ *
+ * 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.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c/twl.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/twl4030-madc.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/stddef.h>
+#include <linux/sysfs.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <plat/scm.h>
+
+static ssize_t show_name(struct device *dev,
+			 struct device_attribute *attr, char *buf)
+{
+	struct temp_sensor_hwmon *tsh = dev_get_drvdata(dev);
+
+	return sprintf(buf, tsh->name);
+}
+
+static ssize_t show_temp_max(struct device *dev,
+			     struct device_attribute *devattr, char *buf)
+{
+	struct temp_sensor_hwmon *tsh = dev_get_drvdata(dev);
+	struct platform_device *pdev = container_of(dev,
+						struct platform_device, dev);
+	int id = pdev->id;
+	int temp;
+
+	temp = omap4460plus_scm_show_temp_max(tsh->scm_ptr, id);
+
+	return sprintf(buf, "%d\n", temp);
+}
+
+static ssize_t set_temp_max(struct device *dev,
+			    struct device_attribute *devattr,
+			    const char *buf, size_t count)
+{
+	struct temp_sensor_hwmon *tsh = dev_get_drvdata(dev);
+	struct platform_device *pdev = container_of(dev,
+						struct platform_device, dev);
+	int id = pdev->id, ret;
+	long val;
+
+	if (strict_strtol(buf, 10, &val))
+		return -EINVAL;
+	ret = omap4460plus_scm_set_temp_max(tsh->scm_ptr, id, val);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static ssize_t show_temp_max_hyst(struct device *dev,
+				  struct device_attribute *devattr, char *buf)
+{
+	struct temp_sensor_hwmon *tsh = dev_get_drvdata(dev);
+	struct platform_device *pdev = container_of(dev,
+						struct platform_device, dev);
+	int id = pdev->id;
+	int temp;
+
+	temp = omap4460plus_scm_show_temp_max_hyst(tsh->scm_ptr, id);
+
+	return sprintf(buf, "%d\n", temp);
+}
+
+static ssize_t set_temp_max_hyst(struct device *dev,
+				 struct device_attribute *devattr,
+				 const char *buf, size_t count)
+{
+	struct temp_sensor_hwmon *tsh = dev_get_drvdata(dev);
+	struct platform_device *pdev = container_of(dev,
+						struct platform_device, dev);
+	int id = pdev->id, ret;
+	long val;
+
+	if (strict_strtol(buf, 10, &val))
+		return -EINVAL;
+	ret = omap4460plus_scm_set_temp_max_hyst(tsh->scm_ptr, id, val);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static ssize_t show_update_interval(struct device *dev,
+				    struct device_attribute *devattr, char *buf)
+{
+	int time = 0;
+	struct temp_sensor_hwmon *tsh = dev_get_drvdata(dev);
+	struct platform_device *pdev = container_of(dev,
+						struct platform_device, dev);
+	int id = pdev->id;
+
+	time = omap4460plus_scm_show_update_interval(tsh->scm_ptr, id);
+
+	return sprintf(buf, "%d\n", time);
+}
+
+static ssize_t set_update_interval(struct device *dev,
+				   struct device_attribute *devattr,
+				   const char *buf, size_t count)
+{
+	struct temp_sensor_hwmon *tsh = dev_get_drvdata(dev);
+	struct platform_device *pdev = container_of(dev,
+						struct platform_device, dev);
+	int id = pdev->id;
+	long val;
+
+	if (strict_strtol(buf, 10, &val))
+		count = -EINVAL;
+
+
+	if (val < 0)
+		return -EINVAL;
+	omap4460plus_scm_set_update_interval(tsh->scm_ptr, val, id);
+	return count;
+}
+
+static int read_temp(struct device *dev,
+		     struct device_attribute *devattr, char *buf)
+{
+	struct temp_sensor_hwmon *tsh = dev_get_drvdata(dev);
+	struct platform_device *pdev = container_of(dev,
+						struct platform_device, dev);
+	int id = pdev->id;
+	int temp;
+
+	temp = omap4460plus_scm_read_temp(tsh->scm_ptr, id);
+
+	return sprintf(buf, "%d\n", temp);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, read_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
+			  set_temp_max, 0);
+static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_max_hyst,
+			  set_temp_max_hyst, 0);
+static SENSOR_DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO,
+			  show_update_interval, set_update_interval, 0);
+
+static struct attribute *temp_sensor_attributes[] = {
+	&dev_attr_name.attr,
+
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_update_interval.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group temp_sensor_group = {
+	.attrs = temp_sensor_attributes,
+};
+
+static int __devinit omap4460plus_temp_sensor_probe(struct platform_device
+							*pdev)
+{
+	int ret;
+	struct device *hwmon;
+
+	ret = sysfs_create_group(&pdev->dev.kobj, &temp_sensor_group);
+	if (ret)
+		goto err_sysfs;
+	hwmon = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(hwmon)) {
+		dev_err(&pdev->dev, "hwmon_device_register failed.\n");
+		ret = PTR_ERR(hwmon);
+		goto err_reg;
+	}
+
+	return 0;
+
+err_reg:
+	sysfs_remove_group(&pdev->dev.kobj, &temp_sensor_group);
+err_sysfs:
+
+	return ret;
+}
+
+static int __devexit omap4460plus_temp_sensor_remove(struct platform_device
+						     *pdev)
+{
+	hwmon_device_unregister(&pdev->dev);
+	sysfs_remove_group(&pdev->dev.kobj, &temp_sensor_group);
+
+	return 0;
+}
+
+static struct platform_driver omap4460plus_temp_sensor_driver = {
+	.probe = omap4460plus_temp_sensor_probe,
+	.remove = omap4460plus_temp_sensor_remove,
+	.driver = {
+		   .name = "temp_sensor_hwmon",
+		   },
+};
+
+int __init omap4460plus_temp_sensor_init(void)
+{
+	return platform_driver_register(&omap4460plus_temp_sensor_driver);
+}
+
+module_init(omap4460plus_temp_sensor_init);
+
+static void __exit omap4460plus_temp_sensor_exit(void)
+{
+	platform_driver_unregister(&omap4460plus_temp_sensor_driver);
+}
+
+module_exit(omap4460plus_temp_sensor_exit);
+
+MODULE_DESCRIPTION("OMAP446X temperature sensor Hwmon Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("J Keerthy <j-keerthy@xxxxxx>");
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux