misc: Initial NCT1008 driver
Greg Meiste [Tue, 16 Nov 2010 19:33:06 +0000 (13:33 -0600)]
Initial version of the NCT1008 driver to turn off the sensor when the
device is suspended.  This improves standby current drain.

Change-Id: Ia64613c33c0052434d5e304c434605611e5ef789
Signed-off-by: Greg Meiste <w30289@motorola.com>

Rebase-Id: R868814b9f4ec4ed834765d774195aad475bb7dcf

drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/nct1008.c [new file with mode: 0755]
include/linux/nct1008.h [new file with mode: 0644]

index c779509..b560699 100644 (file)
@@ -382,6 +382,14 @@ config HMC6352
          This driver provides support for the Honeywell HMC6352 compass,
          providing configuration and heading data via sysfs.
 
+config SENSORS_NCT1008
+       tristate "ON Semiconductor Temperature Sensor"
+       default n
+       depends on I2C
+       help
+        Say yes here if you wish to include the ON Semiconductor
+        NCT1008 Temperature sensor.
+
 config EP93XX_PWM
        tristate "EP93xx PWM support"
        depends on ARCH_EP93XX
index 3e1d801..6734746 100644 (file)
@@ -49,3 +49,4 @@ obj-y                         += carma/
 obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
 obj-$(CONFIG_ALTERA_STAPL)     +=altera-stapl/
 obj-$(CONFIG_MAX8997_MUIC)     += max8997-muic.o
+obj-$(CONFIG_SENSORS_NCT1008)  += nct1008.o
diff --git a/drivers/misc/nct1008.c b/drivers/misc/nct1008.c
new file mode 100755 (executable)
index 0000000..a29e984
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2010 Motorola, Inc.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/nct1008.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+
+#define NCT_BIT_CONFIG_RUN_STOP 6
+
+struct nct1008_data {
+       struct i2c_client *client;
+};
+
+static uint32_t nct1008_debug;
+module_param_named(temp_debug, nct1008_debug, uint, 0664);
+
+static int nct1008_run(struct nct1008_data *nct, u8 run)
+{
+       int err;
+       u8 rd_val;
+       u8 wr_val;
+
+       rd_val = i2c_smbus_read_byte_data(nct->client, NCT_CONFIG_RD);
+       if (rd_val < 0) {
+               pr_err("%s: config register read fail: %d\n", __func__, rd_val);
+               return rd_val;
+       }
+
+       if (nct1008_debug)
+               pr_info("%s: Previous config is 0x%02x\n", __func__, rd_val);
+
+       if (run)
+               wr_val = rd_val & ~(1 << NCT_BIT_CONFIG_RUN_STOP);
+       else
+               wr_val = rd_val | (1 << NCT_BIT_CONFIG_RUN_STOP);
+       err = i2c_smbus_write_byte_data(nct->client, NCT_CONFIG_WR, wr_val);
+       if (err)
+               pr_err("%s: setting RUN/STOP failed: %d\n", __func__, err);
+
+       return err;
+}
+
+static int nct1008_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       struct nct1008_data *nct;
+
+       nct = kzalloc(sizeof(struct nct1008_data), GFP_KERNEL);
+       if (nct == NULL)
+               return -ENOMEM;
+
+       nct->client = client;
+       i2c_set_clientdata(client, nct);
+
+       return 0;
+}
+
+static int nct1008_remove(struct i2c_client *client)
+{
+       struct nct1008_data *nct = i2c_get_clientdata(client);
+
+       kfree(nct);
+       return 0;
+}
+
+static int nct1008_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+       struct nct1008_data *nct = i2c_get_clientdata(client);
+
+       if (nct1008_debug)
+               pr_info("%s: Suspending\n", __func__);
+
+       return nct1008_run(nct, 0);
+}
+
+static int nct1008_resume(struct i2c_client *client)
+{
+       struct nct1008_data *nct = i2c_get_clientdata(client);
+
+       if (nct1008_debug)
+               pr_info("%s: Resuming\n", __func__);
+
+       return nct1008_run(nct, 1);
+}
+
+static const struct i2c_device_id nct1008_id[] = {
+       {"nct1008", 0},
+       {}
+};
+
+static struct i2c_driver nct1008_i2c_driver = {
+       .probe = nct1008_probe,
+       .remove = nct1008_remove,
+       .suspend = nct1008_suspend,
+       .resume = nct1008_resume,
+       .id_table = nct1008_id,
+       .driver = {
+               .name = "nct1008",
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init nct1008_init(void)
+{
+       return i2c_add_driver(&nct1008_i2c_driver);
+}
+
+static void __exit nct1008_exit(void)
+{
+       i2c_del_driver(&nct1008_i2c_driver);
+}
+
+module_init(nct1008_init);
+module_exit(nct1008_exit);
+
+MODULE_DESCRIPTION("Temperature sensor driver for OnSemi NCT1008");
+MODULE_AUTHOR("Motorola");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/nct1008.h b/include/linux/nct1008.h
new file mode 100644 (file)
index 0000000..c6b3962
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 Motorola, Inc.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#ifndef _LINUX_NCT1008_H__
+#define _LINUX_NCT1008_H__
+
+/* NCT1008 Read Only Registers */
+#define NCT_LOCAL_TEMP_RD                      0x00
+#define NCT_EXT_TEMP_HIGH_RD                   0x01
+#define NCT_EXT_TEMP_LOW_RD                    0x10
+#define NCT_STATUS_RD                          0x02
+
+/* NCT1008 Control Registers */
+#define NCT_CONFIG_RD                          0x03
+#define NCT_CONFIG_WR                          0x09
+#define NCT_CONV_RATE_RD                       0x04
+#define NCT_CONV_RATE_WR                       0x0A
+
+/* NCT1008 Limit Registers */
+#define NCT_LOCAL_TEMP_HIGH_LIMIT_RD           0x05
+#define NCT_LOCAL_TEMP_LOW_LIMIT_RD            0x06
+#define NCT_LOCAL_TEMP_HIGH_LIMIT_WR           0x0B
+#define NCT_LOCAL_TEMP_LOW_LIMIT_WR            0x0C
+
+#define NCT_EXT_TEMP_HIGH_LIMIT_HBYTE_RD       0x07
+#define NCT_EXT_TEMP_LOW_LIMIT_HBYTE_RD                0x08
+#define NCT_EXT_TEMP_HIGH_LIMIT_HBYTE_WR       0x0D
+#define NCT_EXT_TEMP_LOW_LIMIT_HBYTE_WR                0x0E
+#define NCT_EXT_TEMP_HIGH_LIMIT_LBYTE_RDWR     0x13
+#define NCT_EXT_TEMP_LOW_LIMIT_LBYTE_RDWR      0x14
+#define NCT_EXT_THERM_LIMIT                    0x19
+#define NCT_LOCAL_THERM_LIMIT                  0x20
+
+#define NCT_EXT_TEMP_OFFSET_HIGH_RDWR          0x11
+#define NCT_EXT_TEMP_OFFSET_LOW_RDWR           0x12
+#define NCT_THERM_HYST                         0x21
+#define NCT_CONSEC_ALERT                       0x22
+
+#endif /* _LINUX_NCT1008_H__ */