All of lore.kernel.org
 help / color / mirror / Atom feed
From: gregkh@suse.de (Greg KH)
To: linux-kernel@vger.kernel.org, sensors@Stimpy.netroedge.com
Cc: khali@linux-fr.org
Subject: [PATCH] I2C: New lm92 chip driver
Date: Thu, 19 May 2005 06:25:47 +0000	[thread overview]
Message-ID: <11123113902683@kroah.com> (raw)
In-Reply-To: <11123113893610@kroah.com>

ChangeSet 1.2324, 2005/03/31 14:05:50-08:00, khali@linux-fr.org

[PATCH] I2C: New lm92 chip driver

This is a new i2c chip driver named lm92. It supports the National
Semiconductor LM92 and Maxim MAX6635 chips. This time I did not port the
driver from the lm_sensors project but instead rewrote it. The reason is
that the original driver has a different structure from the other i2c
chip drivers, which would have made maintenance harder.

I don't have a compatible chip myself but could test my code thanks to
Mark Hoffman's i2c-stub fake bus driver. Later on, James Chapman tested
it on a real chip, successfully.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>


 drivers/i2c/chips/Kconfig  |   11 +
 drivers/i2c/chips/Makefile |    1 
 drivers/i2c/chips/lm92.c   |  423 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 435 insertions(+)


diff -Nru a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
--- a/drivers/i2c/chips/Kconfig	2005-03-31 15:19:07 -08:00
+++ b/drivers/i2c/chips/Kconfig	2005-03-31 15:19:07 -08:00
@@ -236,6 +236,17 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm90.
 
+config SENSORS_LM92
+	tristate "National Semiconductor LM92 and compatibles"
+	depends on I2C && EXPERIMENTAL
+	select I2C_SENSOR
+	help
+	  If you say yes here you get support for National Semiconductor LM92
+	  and Maxim MAX6635 sensor chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called lm92.
+
 config SENSORS_MAX1619
 	tristate "Maxim MAX1619 sensor chip"
 	depends on I2C && EXPERIMENTAL
diff -Nru a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
--- a/drivers/i2c/chips/Makefile	2005-03-31 15:19:07 -08:00
+++ b/drivers/i2c/chips/Makefile	2005-03-31 15:19:07 -08:00
@@ -27,6 +27,7 @@
 obj-$(CONFIG_SENSORS_LM85)	+= lm85.o
 obj-$(CONFIG_SENSORS_LM87)	+= lm87.o
 obj-$(CONFIG_SENSORS_LM90)	+= lm90.o
+obj-$(CONFIG_SENSORS_LM92)	+= lm92.o
 obj-$(CONFIG_SENSORS_MAX1619)	+= max1619.o
 obj-$(CONFIG_SENSORS_M41T00)	+= m41t00.o
 obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
diff -Nru a/drivers/i2c/chips/lm92.c b/drivers/i2c/chips/lm92.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/chips/lm92.c	2005-03-31 15:19:07 -08:00
@@ -0,0 +1,423 @@
+/*
+ * lm92 - Hardware monitoring driver
+ * Copyright (C) 2005  Jean Delvare <khali@linux-fr.org>
+ *
+ * Based on the lm90 driver, with some ideas taken from the lm_sensors
+ * lm92 driver as well.
+ *
+ * The LM92 is a sensor chip made by National Semiconductor. It reports
+ * its own temperature with a 0.0625 deg resolution and a 0.33 deg
+ * accuracy. Complete datasheet can be obtained from National's website
+ * at:
+ *   http://www.national.com/pf/LM/LM92.html
+ *
+ * This driver also supports the MAX6635 sensor chip made by Maxim.
+ * This chip is compatible with the LM92, but has a lesser accuracy
+ * (1.0 deg). Complete datasheet can be obtained from Maxim's website
+ * at:
+ *   http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3074
+ *
+ * Since the LM92 was the first chipset supported by this driver, most
+ * comments will refer to this chipset, but are actually general and
+ * concern all supported chipsets, unless mentioned otherwise.
+ *
+ * Support could easily be added for the National Semiconductor LM76
+ * and Maxim MAX6633 and MAX6634 chips, which are mostly compatible
+ * with the LM92.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+
+
+/* The LM92 and MAX6635 have 2 two-state pins for address selection,
+   resulting in 4 possible addresses. */
+static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
+				       I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(lm92);
+
+/* The LM92 registers */
+#define LM92_REG_CONFIG			0x01 /* 8-bit, RW */
+#define LM92_REG_TEMP			0x00 /* 16-bit, RO */
+#define LM92_REG_TEMP_HYST		0x02 /* 16-bit, RW */
+#define LM92_REG_TEMP_CRIT		0x03 /* 16-bit, RW */
+#define LM92_REG_TEMP_LOW		0x04 /* 16-bit, RW */
+#define LM92_REG_TEMP_HIGH		0x05 /* 16-bit, RW */
+#define LM92_REG_MAN_ID			0x07 /* 16-bit, RO, LM92 only */
+
+/* The LM92 uses signed 13-bit values with LSB = 0.0625 degree Celsius,
+   left-justified in 16-bit registers. No rounding is done, with such
+   a resolution it's just not worth it. Note that the MAX6635 doesn't
+   make use of the 4 lower bits for limits (i.e. effective resolution
+   for limits is 1 degree Celsius). */
+static inline int TEMP_FROM_REG(s16 reg)
+{
+	return reg / 8 * 625 / 10;
+}
+
+static inline s16 TEMP_TO_REG(int val)
+{
+	if (val <= -60000)
+		return -60000 * 10 / 625 * 8;
+	if (val >= 160000)
+		return 160000 * 10 / 625 * 8;
+	return val * 10 / 625 * 8;
+}
+
+/* Alarm flags are stored in the 3 LSB of the temperature register */
+static inline u8 ALARMS_FROM_REG(s16 reg)
+{
+	return reg & 0x0007;
+}
+
+/* Driver data (common to all clients) */
+static struct i2c_driver lm92_driver;
+
+/* Client data (each client gets its own) */
+struct lm92_data {
+	struct i2c_client client;
+	struct semaphore update_lock;
+	char valid; /* zero until following fields are valid */
+	unsigned long last_updated; /* in jiffies */
+
+	/* registers values */
+	s16 temp1_input, temp1_crit, temp1_min, temp1_max, temp1_hyst;
+};
+
+
+/*
+ * Sysfs attributes and callback functions
+ */
+
+static struct lm92_data *lm92_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm92_data *data = i2c_get_clientdata(client);
+
+	down(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ)
+	 || !data->valid) {
+		dev_dbg(&client->dev, "Updating lm92 data\n");
+		data->temp1_input = swab16(i2c_smbus_read_word_data(client,
+				    LM92_REG_TEMP));
+		data->temp1_hyst = swab16(i2c_smbus_read_word_data(client,
+				    LM92_REG_TEMP_HYST));
+		data->temp1_crit = swab16(i2c_smbus_read_word_data(client,
+				    LM92_REG_TEMP_CRIT));
+		data->temp1_min = swab16(i2c_smbus_read_word_data(client,
+				    LM92_REG_TEMP_LOW));
+		data->temp1_max = swab16(i2c_smbus_read_word_data(client,
+				    LM92_REG_TEMP_HIGH));
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	up(&data->update_lock);
+
+	return data;
+}
+
+#define show_temp(value) \
+static ssize_t show_##value(struct device *dev, char *buf) \
+{ \
+	struct lm92_data *data = lm92_update_device(dev); \
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \
+}
+show_temp(temp1_input);
+show_temp(temp1_crit);
+show_temp(temp1_min);
+show_temp(temp1_max);
+
+#define set_temp(value, reg) \
+static ssize_t set_##value(struct device *dev, const char *buf, \
+	size_t count) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct lm92_data *data = i2c_get_clientdata(client); \
+	long val = simple_strtol(buf, NULL, 10); \
+	data->value = TEMP_TO_REG(val); \
+	i2c_smbus_write_word_data(client, reg, swab16(data->value)); \
+	return count; \
+}
+set_temp(temp1_crit, LM92_REG_TEMP_CRIT);
+set_temp(temp1_min, LM92_REG_TEMP_LOW);
+set_temp(temp1_max, LM92_REG_TEMP_HIGH);
+
+static ssize_t show_temp1_crit_hyst(struct device *dev, char *buf)
+{
+	struct lm92_data *data = lm92_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_crit)
+		       - TEMP_FROM_REG(data->temp1_hyst));
+}
+static ssize_t show_temp1_max_hyst(struct device *dev, char *buf)
+{
+	struct lm92_data *data = lm92_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_max)
+		       - TEMP_FROM_REG(data->temp1_hyst));
+}
+static ssize_t show_temp1_min_hyst(struct device *dev, char *buf)
+{
+	struct lm92_data *data = lm92_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_min)
+		       + TEMP_FROM_REG(data->temp1_hyst));
+}
+
+static ssize_t set_temp1_crit_hyst(struct device *dev, const char *buf,
+	size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm92_data *data = i2c_get_clientdata(client);
+	data->temp1_hyst = TEMP_FROM_REG(data->temp1_crit) -
+			   simple_strtol(buf, NULL, 10);
+	i2c_smbus_write_word_data(client, LM92_REG_TEMP_HYST,
+				  swab16(TEMP_TO_REG(data->temp1_hyst)));
+	return count;
+}
+
+static ssize_t show_alarms(struct device *dev, char *buf)
+{
+	struct lm92_data *data = lm92_update_device(dev);
+	return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->temp1_input));
+}
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1_input, NULL);
+static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp1_crit,
+	set_temp1_crit);
+static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp1_crit_hyst,
+	set_temp1_crit_hyst);
+static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp1_min,
+	set_temp1_min);
+static DEVICE_ATTR(temp1_min_hyst, S_IRUGO, show_temp1_min_hyst, NULL);
+static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp1_max,
+	set_temp1_max);
+static DEVICE_ATTR(temp1_max_hyst, S_IRUGO, show_temp1_max_hyst, NULL);
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+
+
+/*
+ * Detection and registration
+ */
+
+static void lm92_init_client(struct i2c_client *client)
+{
+	u8 config;
+
+	/* Start the conversions if needed */
+	config = i2c_smbus_read_byte_data(client, LM92_REG_CONFIG);
+	if (config & 0x01)
+		i2c_smbus_write_byte_data(client, LM92_REG_CONFIG,
+					  config & 0xFE);
+}
+
+/* The MAX6635 has no identification register, so we have to use tricks
+   to identify it reliably. This is somewhat slow.
+   Note that we do NOT rely on the 2 MSB of the configuration register
+   always reading 0, as suggested by the datasheet, because it was once
+   reported not to be true. */
+static int max6635_check(struct i2c_client *client)
+{
+	u16 temp_low, temp_high, temp_hyst, temp_crit;
+	u8 conf;
+	int i;
+
+	/* No manufacturer ID register, so a read from this address will
+	   always return the last read value. */
+	temp_low = i2c_smbus_read_word_data(client, LM92_REG_TEMP_LOW);
+	if (i2c_smbus_read_word_data(client, LM92_REG_MAN_ID) != temp_low)
+		return 0;
+	temp_high = i2c_smbus_read_word_data(client, LM92_REG_TEMP_HIGH);
+	if (i2c_smbus_read_word_data(client, LM92_REG_MAN_ID) != temp_high)
+		return 0;
+	
+	/* Limits are stored as integer values (signed, 9-bit). */
+	if ((temp_low & 0x7f00) || (temp_high & 0x7f00))
+		return 0;
+	temp_hyst = i2c_smbus_read_word_data(client, LM92_REG_TEMP_HYST);
+	temp_crit = i2c_smbus_read_word_data(client, LM92_REG_TEMP_CRIT);
+	if ((temp_hyst & 0x7f00) || (temp_crit & 0x7f00))
+		return 0;
+
+	/* Registers addresses were found to cycle over 16-byte boundaries.
+	   We don't test all registers with all offsets so as to save some
+	   reads and time, but this should still be sufficient to dismiss
+	   non-MAX6635 chips. */
+	conf = i2c_smbus_read_byte_data(client, LM92_REG_CONFIG);
+	for (i\x16; i<96; i*=2) {
+		if (temp_hyst != i2c_smbus_read_word_data(client,
+		 		 LM92_REG_TEMP_HYST + i - 16)
+		 || temp_crit != i2c_smbus_read_word_data(client,
+		 		 LM92_REG_TEMP_CRIT + i)
+		 || temp_low != i2c_smbus_read_word_data(client,
+				LM92_REG_TEMP_LOW + i + 16)
+		 || temp_high != i2c_smbus_read_word_data(client,
+		 		 LM92_REG_TEMP_HIGH + i + 32)
+		 || conf != i2c_smbus_read_byte_data(client,
+		 	    LM92_REG_CONFIG + i))
+			return 0;
+	}
+
+	return 1;
+}
+
+/* The following function does more than just detection. If detection
+   succeeds, it also registers the new chip. */
+static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *new_client;
+	struct lm92_data *data;
+	int err = 0;
+	char *name;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
+					    | I2C_FUNC_SMBUS_WORD_DATA))
+		goto exit;
+
+	if (!(data = kmalloc(sizeof(struct lm92_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+	memset(data, 0, sizeof(struct lm92_data));
+
+	/* Fill in enough client fields so that we can read from the chip,
+	   which is required for identication */
+	new_client = &data->client;
+	i2c_set_clientdata(new_client, data);
+	new_client->addr = address;
+	new_client->adapter = adapter;
+	new_client->driver = &lm92_driver;
+	new_client->flags = 0;
+
+	/* A negative kind means that the driver was loaded with no force
+	   parameter (default), so we must identify the chip. */
+	if (kind < 0) {
+		u8 config = i2c_smbus_read_byte_data(new_client,
+			     LM92_REG_CONFIG);
+		u16 man_id = i2c_smbus_read_word_data(new_client,
+			     LM92_REG_MAN_ID);
+
+		if ((config & 0xe0) = 0x00
+		 && man_id = 0x0180) {
+			pr_info("lm92: Found National Semiconductor LM92 chip\n");
+	 		kind = lm92;
+		} else
+		if (max6635_check(new_client)) {
+			pr_info("lm92: Found Maxim MAX6635 chip\n");
+			kind = lm92; /* No separate prefix */
+		}
+		else
+			goto exit_free;
+	} else
+	if (kind = 0) /* Default to an LM92 if forced */
+		kind = lm92;
+
+	/* Give it the proper name */
+	if (kind = lm92) {
+		name = "lm92";
+	} else { /* Supposedly cannot happen */
+		dev_dbg(&new_client->dev, "Kind out of range?\n");
+		goto exit_free;
+	}
+
+	/* Fill in the remaining client fields */
+	strlcpy(new_client->name, name, I2C_NAME_SIZE);
+	data->valid = 0;
+	init_MUTEX(&data->update_lock);
+
+	/* Tell the i2c subsystem a new client has arrived */
+	if ((err = i2c_attach_client(new_client)))
+		goto exit_free;
+
+	/* Initialize the chipset */
+	lm92_init_client(new_client);
+
+	/* Register sysfs hooks */
+	device_create_file(&new_client->dev, &dev_attr_temp1_input);
+	device_create_file(&new_client->dev, &dev_attr_temp1_crit);
+	device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);
+	device_create_file(&new_client->dev, &dev_attr_temp1_min);
+	device_create_file(&new_client->dev, &dev_attr_temp1_min_hyst);
+	device_create_file(&new_client->dev, &dev_attr_temp1_max);
+	device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
+	device_create_file(&new_client->dev, &dev_attr_alarms);
+
+	return 0;
+
+exit_free:
+	kfree(data);
+exit:
+	return err;
+}
+
+static int lm92_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!(adapter->class & I2C_CLASS_HWMON))
+		return 0;
+	return i2c_detect(adapter, &addr_data, lm92_detect);
+}
+
+static int lm92_detach_client(struct i2c_client *client)
+{
+	int err;
+
+	if ((err = i2c_detach_client(client))) {
+		dev_err(&client->dev, "Client deregistration failed, "
+			"client not detached.\n");
+		return err;
+	}
+
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+
+/*
+ * Module and driver stuff
+ */
+
+static struct i2c_driver lm92_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "lm92",
+	.id		= I2C_DRIVERID_LM92,
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= lm92_attach_adapter,
+	.detach_client	= lm92_detach_client,
+};
+
+static int __init sensors_lm92_init(void)
+{
+	return i2c_add_driver(&lm92_driver);
+}
+
+static void __exit sensors_lm92_exit(void)
+{
+	i2c_del_driver(&lm92_driver);
+}
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
+MODULE_DESCRIPTION("LM92/MAX6635 driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_lm92_init);
+module_exit(sensors_lm92_exit);


WARNING: multiple messages have this Message-ID (diff)
From: Greg KH <gregkh@suse.de>
To: linux-kernel@vger.kernel.org, sensors@Stimpy.netroedge.com
Cc: khali@linux-fr.org
Subject: [PATCH] I2C: New lm92 chip driver
Date: Thu, 31 Mar 2005 15:23:10 -0800	[thread overview]
Message-ID: <11123113902683@kroah.com> (raw)
In-Reply-To: <11123113893610@kroah.com>

ChangeSet 1.2324, 2005/03/31 14:05:50-08:00, khali@linux-fr.org

[PATCH] I2C: New lm92 chip driver

This is a new i2c chip driver named lm92. It supports the National
Semiconductor LM92 and Maxim MAX6635 chips. This time I did not port the
driver from the lm_sensors project but instead rewrote it. The reason is
that the original driver has a different structure from the other i2c
chip drivers, which would have made maintenance harder.

I don't have a compatible chip myself but could test my code thanks to
Mark Hoffman's i2c-stub fake bus driver. Later on, James Chapman tested
it on a real chip, successfully.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>


 drivers/i2c/chips/Kconfig  |   11 +
 drivers/i2c/chips/Makefile |    1 
 drivers/i2c/chips/lm92.c   |  423 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 435 insertions(+)


diff -Nru a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
--- a/drivers/i2c/chips/Kconfig	2005-03-31 15:19:07 -08:00
+++ b/drivers/i2c/chips/Kconfig	2005-03-31 15:19:07 -08:00
@@ -236,6 +236,17 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm90.
 
+config SENSORS_LM92
+	tristate "National Semiconductor LM92 and compatibles"
+	depends on I2C && EXPERIMENTAL
+	select I2C_SENSOR
+	help
+	  If you say yes here you get support for National Semiconductor LM92
+	  and Maxim MAX6635 sensor chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called lm92.
+
 config SENSORS_MAX1619
 	tristate "Maxim MAX1619 sensor chip"
 	depends on I2C && EXPERIMENTAL
diff -Nru a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
--- a/drivers/i2c/chips/Makefile	2005-03-31 15:19:07 -08:00
+++ b/drivers/i2c/chips/Makefile	2005-03-31 15:19:07 -08:00
@@ -27,6 +27,7 @@
 obj-$(CONFIG_SENSORS_LM85)	+= lm85.o
 obj-$(CONFIG_SENSORS_LM87)	+= lm87.o
 obj-$(CONFIG_SENSORS_LM90)	+= lm90.o
+obj-$(CONFIG_SENSORS_LM92)	+= lm92.o
 obj-$(CONFIG_SENSORS_MAX1619)	+= max1619.o
 obj-$(CONFIG_SENSORS_M41T00)	+= m41t00.o
 obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
diff -Nru a/drivers/i2c/chips/lm92.c b/drivers/i2c/chips/lm92.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/chips/lm92.c	2005-03-31 15:19:07 -08:00
@@ -0,0 +1,423 @@
+/*
+ * lm92 - Hardware monitoring driver
+ * Copyright (C) 2005  Jean Delvare <khali@linux-fr.org>
+ *
+ * Based on the lm90 driver, with some ideas taken from the lm_sensors
+ * lm92 driver as well.
+ *
+ * The LM92 is a sensor chip made by National Semiconductor. It reports
+ * its own temperature with a 0.0625 deg resolution and a 0.33 deg
+ * accuracy. Complete datasheet can be obtained from National's website
+ * at:
+ *   http://www.national.com/pf/LM/LM92.html
+ *
+ * This driver also supports the MAX6635 sensor chip made by Maxim.
+ * This chip is compatible with the LM92, but has a lesser accuracy
+ * (1.0 deg). Complete datasheet can be obtained from Maxim's website
+ * at:
+ *   http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3074
+ *
+ * Since the LM92 was the first chipset supported by this driver, most
+ * comments will refer to this chipset, but are actually general and
+ * concern all supported chipsets, unless mentioned otherwise.
+ *
+ * Support could easily be added for the National Semiconductor LM76
+ * and Maxim MAX6633 and MAX6634 chips, which are mostly compatible
+ * with the LM92.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+
+
+/* The LM92 and MAX6635 have 2 two-state pins for address selection,
+   resulting in 4 possible addresses. */
+static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
+				       I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(lm92);
+
+/* The LM92 registers */
+#define LM92_REG_CONFIG			0x01 /* 8-bit, RW */
+#define LM92_REG_TEMP			0x00 /* 16-bit, RO */
+#define LM92_REG_TEMP_HYST		0x02 /* 16-bit, RW */
+#define LM92_REG_TEMP_CRIT		0x03 /* 16-bit, RW */
+#define LM92_REG_TEMP_LOW		0x04 /* 16-bit, RW */
+#define LM92_REG_TEMP_HIGH		0x05 /* 16-bit, RW */
+#define LM92_REG_MAN_ID			0x07 /* 16-bit, RO, LM92 only */
+
+/* The LM92 uses signed 13-bit values with LSB = 0.0625 degree Celsius,
+   left-justified in 16-bit registers. No rounding is done, with such
+   a resolution it's just not worth it. Note that the MAX6635 doesn't
+   make use of the 4 lower bits for limits (i.e. effective resolution
+   for limits is 1 degree Celsius). */
+static inline int TEMP_FROM_REG(s16 reg)
+{
+	return reg / 8 * 625 / 10;
+}
+
+static inline s16 TEMP_TO_REG(int val)
+{
+	if (val <= -60000)
+		return -60000 * 10 / 625 * 8;
+	if (val >= 160000)
+		return 160000 * 10 / 625 * 8;
+	return val * 10 / 625 * 8;
+}
+
+/* Alarm flags are stored in the 3 LSB of the temperature register */
+static inline u8 ALARMS_FROM_REG(s16 reg)
+{
+	return reg & 0x0007;
+}
+
+/* Driver data (common to all clients) */
+static struct i2c_driver lm92_driver;
+
+/* Client data (each client gets its own) */
+struct lm92_data {
+	struct i2c_client client;
+	struct semaphore update_lock;
+	char valid; /* zero until following fields are valid */
+	unsigned long last_updated; /* in jiffies */
+
+	/* registers values */
+	s16 temp1_input, temp1_crit, temp1_min, temp1_max, temp1_hyst;
+};
+
+
+/*
+ * Sysfs attributes and callback functions
+ */
+
+static struct lm92_data *lm92_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm92_data *data = i2c_get_clientdata(client);
+
+	down(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ)
+	 || !data->valid) {
+		dev_dbg(&client->dev, "Updating lm92 data\n");
+		data->temp1_input = swab16(i2c_smbus_read_word_data(client,
+				    LM92_REG_TEMP));
+		data->temp1_hyst = swab16(i2c_smbus_read_word_data(client,
+				    LM92_REG_TEMP_HYST));
+		data->temp1_crit = swab16(i2c_smbus_read_word_data(client,
+				    LM92_REG_TEMP_CRIT));
+		data->temp1_min = swab16(i2c_smbus_read_word_data(client,
+				    LM92_REG_TEMP_LOW));
+		data->temp1_max = swab16(i2c_smbus_read_word_data(client,
+				    LM92_REG_TEMP_HIGH));
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	up(&data->update_lock);
+
+	return data;
+}
+
+#define show_temp(value) \
+static ssize_t show_##value(struct device *dev, char *buf) \
+{ \
+	struct lm92_data *data = lm92_update_device(dev); \
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \
+}
+show_temp(temp1_input);
+show_temp(temp1_crit);
+show_temp(temp1_min);
+show_temp(temp1_max);
+
+#define set_temp(value, reg) \
+static ssize_t set_##value(struct device *dev, const char *buf, \
+	size_t count) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct lm92_data *data = i2c_get_clientdata(client); \
+	long val = simple_strtol(buf, NULL, 10); \
+	data->value = TEMP_TO_REG(val); \
+	i2c_smbus_write_word_data(client, reg, swab16(data->value)); \
+	return count; \
+}
+set_temp(temp1_crit, LM92_REG_TEMP_CRIT);
+set_temp(temp1_min, LM92_REG_TEMP_LOW);
+set_temp(temp1_max, LM92_REG_TEMP_HIGH);
+
+static ssize_t show_temp1_crit_hyst(struct device *dev, char *buf)
+{
+	struct lm92_data *data = lm92_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_crit)
+		       - TEMP_FROM_REG(data->temp1_hyst));
+}
+static ssize_t show_temp1_max_hyst(struct device *dev, char *buf)
+{
+	struct lm92_data *data = lm92_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_max)
+		       - TEMP_FROM_REG(data->temp1_hyst));
+}
+static ssize_t show_temp1_min_hyst(struct device *dev, char *buf)
+{
+	struct lm92_data *data = lm92_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_min)
+		       + TEMP_FROM_REG(data->temp1_hyst));
+}
+
+static ssize_t set_temp1_crit_hyst(struct device *dev, const char *buf,
+	size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm92_data *data = i2c_get_clientdata(client);
+	data->temp1_hyst = TEMP_FROM_REG(data->temp1_crit) -
+			   simple_strtol(buf, NULL, 10);
+	i2c_smbus_write_word_data(client, LM92_REG_TEMP_HYST,
+				  swab16(TEMP_TO_REG(data->temp1_hyst)));
+	return count;
+}
+
+static ssize_t show_alarms(struct device *dev, char *buf)
+{
+	struct lm92_data *data = lm92_update_device(dev);
+	return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->temp1_input));
+}
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1_input, NULL);
+static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp1_crit,
+	set_temp1_crit);
+static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp1_crit_hyst,
+	set_temp1_crit_hyst);
+static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp1_min,
+	set_temp1_min);
+static DEVICE_ATTR(temp1_min_hyst, S_IRUGO, show_temp1_min_hyst, NULL);
+static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp1_max,
+	set_temp1_max);
+static DEVICE_ATTR(temp1_max_hyst, S_IRUGO, show_temp1_max_hyst, NULL);
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+
+
+/*
+ * Detection and registration
+ */
+
+static void lm92_init_client(struct i2c_client *client)
+{
+	u8 config;
+
+	/* Start the conversions if needed */
+	config = i2c_smbus_read_byte_data(client, LM92_REG_CONFIG);
+	if (config & 0x01)
+		i2c_smbus_write_byte_data(client, LM92_REG_CONFIG,
+					  config & 0xFE);
+}
+
+/* The MAX6635 has no identification register, so we have to use tricks
+   to identify it reliably. This is somewhat slow.
+   Note that we do NOT rely on the 2 MSB of the configuration register
+   always reading 0, as suggested by the datasheet, because it was once
+   reported not to be true. */
+static int max6635_check(struct i2c_client *client)
+{
+	u16 temp_low, temp_high, temp_hyst, temp_crit;
+	u8 conf;
+	int i;
+
+	/* No manufacturer ID register, so a read from this address will
+	   always return the last read value. */
+	temp_low = i2c_smbus_read_word_data(client, LM92_REG_TEMP_LOW);
+	if (i2c_smbus_read_word_data(client, LM92_REG_MAN_ID) != temp_low)
+		return 0;
+	temp_high = i2c_smbus_read_word_data(client, LM92_REG_TEMP_HIGH);
+	if (i2c_smbus_read_word_data(client, LM92_REG_MAN_ID) != temp_high)
+		return 0;
+	
+	/* Limits are stored as integer values (signed, 9-bit). */
+	if ((temp_low & 0x7f00) || (temp_high & 0x7f00))
+		return 0;
+	temp_hyst = i2c_smbus_read_word_data(client, LM92_REG_TEMP_HYST);
+	temp_crit = i2c_smbus_read_word_data(client, LM92_REG_TEMP_CRIT);
+	if ((temp_hyst & 0x7f00) || (temp_crit & 0x7f00))
+		return 0;
+
+	/* Registers addresses were found to cycle over 16-byte boundaries.
+	   We don't test all registers with all offsets so as to save some
+	   reads and time, but this should still be sufficient to dismiss
+	   non-MAX6635 chips. */
+	conf = i2c_smbus_read_byte_data(client, LM92_REG_CONFIG);
+	for (i=16; i<96; i*=2) {
+		if (temp_hyst != i2c_smbus_read_word_data(client,
+		 		 LM92_REG_TEMP_HYST + i - 16)
+		 || temp_crit != i2c_smbus_read_word_data(client,
+		 		 LM92_REG_TEMP_CRIT + i)
+		 || temp_low != i2c_smbus_read_word_data(client,
+				LM92_REG_TEMP_LOW + i + 16)
+		 || temp_high != i2c_smbus_read_word_data(client,
+		 		 LM92_REG_TEMP_HIGH + i + 32)
+		 || conf != i2c_smbus_read_byte_data(client,
+		 	    LM92_REG_CONFIG + i))
+			return 0;
+	}
+
+	return 1;
+}
+
+/* The following function does more than just detection. If detection
+   succeeds, it also registers the new chip. */
+static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *new_client;
+	struct lm92_data *data;
+	int err = 0;
+	char *name;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
+					    | I2C_FUNC_SMBUS_WORD_DATA))
+		goto exit;
+
+	if (!(data = kmalloc(sizeof(struct lm92_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+	memset(data, 0, sizeof(struct lm92_data));
+
+	/* Fill in enough client fields so that we can read from the chip,
+	   which is required for identication */
+	new_client = &data->client;
+	i2c_set_clientdata(new_client, data);
+	new_client->addr = address;
+	new_client->adapter = adapter;
+	new_client->driver = &lm92_driver;
+	new_client->flags = 0;
+
+	/* A negative kind means that the driver was loaded with no force
+	   parameter (default), so we must identify the chip. */
+	if (kind < 0) {
+		u8 config = i2c_smbus_read_byte_data(new_client,
+			     LM92_REG_CONFIG);
+		u16 man_id = i2c_smbus_read_word_data(new_client,
+			     LM92_REG_MAN_ID);
+
+		if ((config & 0xe0) == 0x00
+		 && man_id == 0x0180) {
+			pr_info("lm92: Found National Semiconductor LM92 chip\n");
+	 		kind = lm92;
+		} else
+		if (max6635_check(new_client)) {
+			pr_info("lm92: Found Maxim MAX6635 chip\n");
+			kind = lm92; /* No separate prefix */
+		}
+		else
+			goto exit_free;
+	} else
+	if (kind == 0) /* Default to an LM92 if forced */
+		kind = lm92;
+
+	/* Give it the proper name */
+	if (kind == lm92) {
+		name = "lm92";
+	} else { /* Supposedly cannot happen */
+		dev_dbg(&new_client->dev, "Kind out of range?\n");
+		goto exit_free;
+	}
+
+	/* Fill in the remaining client fields */
+	strlcpy(new_client->name, name, I2C_NAME_SIZE);
+	data->valid = 0;
+	init_MUTEX(&data->update_lock);
+
+	/* Tell the i2c subsystem a new client has arrived */
+	if ((err = i2c_attach_client(new_client)))
+		goto exit_free;
+
+	/* Initialize the chipset */
+	lm92_init_client(new_client);
+
+	/* Register sysfs hooks */
+	device_create_file(&new_client->dev, &dev_attr_temp1_input);
+	device_create_file(&new_client->dev, &dev_attr_temp1_crit);
+	device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);
+	device_create_file(&new_client->dev, &dev_attr_temp1_min);
+	device_create_file(&new_client->dev, &dev_attr_temp1_min_hyst);
+	device_create_file(&new_client->dev, &dev_attr_temp1_max);
+	device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
+	device_create_file(&new_client->dev, &dev_attr_alarms);
+
+	return 0;
+
+exit_free:
+	kfree(data);
+exit:
+	return err;
+}
+
+static int lm92_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!(adapter->class & I2C_CLASS_HWMON))
+		return 0;
+	return i2c_detect(adapter, &addr_data, lm92_detect);
+}
+
+static int lm92_detach_client(struct i2c_client *client)
+{
+	int err;
+
+	if ((err = i2c_detach_client(client))) {
+		dev_err(&client->dev, "Client deregistration failed, "
+			"client not detached.\n");
+		return err;
+	}
+
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+
+/*
+ * Module and driver stuff
+ */
+
+static struct i2c_driver lm92_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "lm92",
+	.id		= I2C_DRIVERID_LM92,
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= lm92_attach_adapter,
+	.detach_client	= lm92_detach_client,
+};
+
+static int __init sensors_lm92_init(void)
+{
+	return i2c_add_driver(&lm92_driver);
+}
+
+static void __exit sensors_lm92_exit(void)
+{
+	i2c_del_driver(&lm92_driver);
+}
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
+MODULE_DESCRIPTION("LM92/MAX6635 driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_lm92_init);
+module_exit(sensors_lm92_exit);


  reply	other threads:[~2005-05-19  6:25 UTC|newest]

Thread overview: 158+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-03-31 23:22 [BK PATCH] I2C patches for 2.6.12-rc1 Greg KH
2005-03-31 23:23 ` [PATCH] i2c/i2c-ite: remove interruptible_sleep_on_timeout() usage Greg KH
2005-05-19  6:25   ` Greg KH
2005-03-31 23:23   ` [PATCH] i2c/i2c-elektor: " Greg KH
2005-05-19  6:25     ` [PATCH] i2c/i2c-elektor: remove interruptible_sleep_on_timeout() Greg KH
2005-03-31 23:23     ` Greg KH [this message]
2005-05-19  6:25       ` [PATCH] I2C: New lm92 chip driver Greg KH
2005-03-31 23:23       ` [PATCH] I2C: Cleanup adm1021 unused defines Greg KH
2005-05-19  6:25         ` Greg KH
2005-03-31 23:23         ` [PATCH] I2C: Fix adm1021 alarms mask Greg KH
2005-05-19  6:25           ` Greg KH
2005-03-31 23:23           ` [PATCH] I2C: Kill unused struct members in w83627hf driver Greg KH
2005-05-19  6:25             ` Greg KH
2005-03-31 23:23             ` [PATCH] I2C: Make master_xfer debug messages more useful Greg KH
2005-05-19  6:25               ` Greg KH
2005-03-31 23:23               ` [PATCH] I2C: Skip broken detection step in it87 Greg KH
2005-05-19  6:25                 ` Greg KH
2005-03-31 23:23                 ` [PATCH] I2C: group Intel on I2C Hardware Bus support Greg KH
2005-05-19  6:25                   ` Greg KH
2005-03-31 23:23                   ` [PATCH] i2c: new driver for ds1337 RTC Greg KH
2005-05-19  6:25                     ` Greg KH
2005-03-31 23:23                     ` [PATCH] i2c: add adt7461 chip support to lm90 driver Greg KH
2005-05-19  6:25                       ` Greg KH
2005-03-31 23:23                       ` [PATCH] I2C: Clean up of i2c-elektor.c build Greg KH
2005-05-19  6:25                         ` Greg KH
2005-03-31 23:23                         ` [PATCH] I2C: Fix breakage in m41t00 i2c rtc driver Greg KH
2005-05-19  6:25                           ` Greg KH
2005-03-31 23:23                           ` [PATCH] I2C: Fix some i2c algorithm initialization Greg KH
2005-05-19  6:25                             ` Greg KH
2005-03-31 23:23                             ` [PATCH] I2C: Kill outdated defines in i2c.h Greg KH
2005-05-19  6:25                               ` Greg KH
2005-03-31 23:23                               ` [PATCH] I2C: Avoid repeated resets of i2c-viapro Greg KH
2005-05-19  6:25                                 ` Greg KH
2005-03-31 23:23                                 ` [PATCH] I2C: Recognize new revision of the ADT7463 chip Greg KH
2005-05-19  6:25                                   ` Greg KH
2005-03-31 23:23                                   ` [PATCH] I2C: Fix Vaio EEPROM detection Greg KH
2005-05-19  6:25                                     ` Greg KH
2005-03-31 23:23                                     ` [PATCH] I2C: busses documentation update 1 of 2 Greg KH
2005-05-19  6:25                                       ` Greg KH
2005-03-31 23:23                                       ` [PATCH] I2C: busses documentation update 2 " Greg KH
2005-05-19  6:25                                         ` Greg KH
2005-03-31 23:23                                         ` [PATCH] I2C: lost arbitration detection for PCF8584 Greg KH
2005-05-19  6:25                                           ` Greg KH
2005-03-31 23:23                                           ` [PATCH] I2C: lsb in emc6d102 and adm1027 Greg KH
2005-05-19  6:25                                             ` Greg KH
2005-03-31 23:23                                             ` [PATCH] I2C: Delete useless instruction in it87 Greg KH
2005-05-19  6:25                                               ` Greg KH
2005-03-31 23:23                                               ` [PATCH] I2C: Fix race condition in it87 driver Greg KH
2005-05-19  6:25                                                 ` Greg KH
2005-03-31 23:23                                                 ` [PATCH] I2C: i2c-s3c2410 functionality and fixes Greg KH
2005-05-19  6:25                                                   ` Greg KH
2005-03-31 23:23                                                   ` [PATCH] i2c: add adt7461 chip support to lm90 driver's Kconfig entry Greg KH
2005-05-19  6:25                                                     ` Greg KH
2005-03-31 23:23                                                     ` [PATCH] I2C: Fix broken force parameter handling Greg KH
2005-05-19  6:25                                                       ` Greg KH
2005-03-31 23:23                                                       ` [PATCH] I2C: Fix indentation of lm87 driver Greg KH
2005-05-19  6:25                                                         ` Greg KH
2005-03-31 23:23                                                         ` [PATCH] I2C: Drop useless w83781d RT feature Greg KH
2005-05-19  6:25                                                           ` Greg KH
2005-03-31 23:23                                                           ` [PATCH] i2c: i2c-mv64xxx - set adapter owner and class fields Greg KH
2005-05-19  6:25                                                             ` Greg KH
2005-04-07  9:45                     ` [PATCH] i2c: new driver for ds1337 RTC Ladislav Michl
2005-05-19  6:25                       ` Ladislav Michl
2005-04-07  9:59                       ` Jean Delvare
2005-05-19  6:25                         ` Jean Delvare
2005-04-07 11:16                         ` Ladislav Michl
2005-05-19  6:25                           ` Ladislav Michl
2005-04-07 13:07                           ` Jean Delvare
2005-05-19  6:25                             ` Jean Delvare
2005-04-07 14:28                             ` Ladislav Michl
2005-05-19  6:25                               ` Ladislav Michl
2005-04-07 21:18                               ` Greg KH
2005-05-19  6:25                                 ` Greg KH
2005-04-07 23:17                                 ` [PATCH] ds1337 1/4 Ladislav Michl
2005-05-19  6:25                                   ` Ladislav Michl
2005-04-07 23:36                                   ` Greg KH
2005-05-19  6:25                                     ` Greg KH
2005-04-08 13:00                                     ` Ladislav Michl
2005-05-19  6:25                                       ` Ladislav Michl
2005-04-08 16:31                                       ` James Chapman
2005-05-19  6:25                                         ` James Chapman
2005-05-02 20:41                                       ` Greg KH
2005-05-19  6:25                                         ` Greg KH
2005-04-08  8:49                                   ` Jean Delvare
2005-05-19  6:25                                     ` Jean Delvare
2005-04-07 23:18                                 ` [PATCH] ds1337 2/4 Ladislav Michl
2005-05-19  6:25                                   ` Ladislav Michl
2005-04-08  8:51                                   ` Jean Delvare
2005-05-19  6:25                                     ` Jean Delvare
2005-04-08 13:02                                     ` Ladislav Michl
2005-05-19  6:25                                       ` Ladislav Michl
2005-05-02 20:41                                       ` Greg KH
2005-05-19  6:25                                         ` Greg KH
2005-04-07 23:18                                 ` [PATCH] ds1337 3/4 Ladislav Michl
2005-05-19  6:25                                   ` Ladislav Michl
2005-04-08 10:08                                   ` Jean Delvare
2005-05-19  6:25                                     ` Jean Delvare
2005-04-08 13:06                                     ` Ladislav Michl
2005-05-19  6:25                                       ` Ladislav Michl
2005-05-02 20:41                                       ` Greg KH
2005-05-19  6:25                                         ` Greg KH
2005-05-04  6:13                                         ` [PATCH] ds1337 1/3 Ladislav Michl
2005-05-19  6:25                                           ` Ladislav Michl
2005-05-04  8:41                                           ` Jean Delvare
2005-05-19  6:25                                             ` Jean Delvare
2005-05-04  6:13                                         ` [PATCH] ds1337 2/3 Ladislav Michl
2005-05-19  6:25                                           ` Ladislav Michl
2005-05-04  9:44                                           ` Jean Delvare
2005-05-19  6:25                                             ` Jean Delvare
2005-05-04  6:14                                         ` [PATCH] ds1337 3/3 Ladislav Michl
2005-05-19  6:25                                           ` Ladislav Michl
2005-05-04 10:07                                           ` Jean Delvare
2005-05-19  6:25                                             ` Jean Delvare
2005-05-10 12:08                                             ` [PATCH] ds1337 driver works also with ds1339 chip Ladislav Michl
2005-05-19  6:25                                               ` Ladislav Michl
2005-05-10 12:40                                               ` Jean Delvare
2005-05-19  6:25                                                 ` Jean Delvare
2005-05-10 12:48                                               ` Russell King
2005-05-19  6:25                                                 ` Russell King
     [not found]                                           ` <1DTwF8-18P-00@press.kroah.org>
     [not found]                                             ` <20050508204021.627f9cd1.khali@linux-fr.org>
     [not found]                                               ` <427E6E21.60001@katalix.com>
     [not found]                                                 ` <20050508222351.08bfe2e1.khali@linux-fr.org>
2005-05-10 12:18                                                   ` [PATCH] ds1337: export ds1337_do_command Ladislav Michl
2005-05-19  6:25                                                     ` Ladislav Michl
2005-05-10 12:51                                                     ` Jean Delvare
2005-05-19  6:25                                                       ` Jean Delvare
2005-05-10 17:55                                                     ` Greg KH
2005-05-19  6:25                                                       ` Greg KH
2005-05-10 18:36                                                       ` Ladislav Michl
2005-05-19  6:25                                                         ` Ladislav Michl
2005-05-10 20:30                                                         ` Greg KH
2005-05-19  6:25                                                           ` Greg KH
2005-05-11  8:32                                                       ` Ladislav Michl
2005-05-19  6:25                                                         ` Ladislav Michl
2005-04-07 23:19                                 ` [PATCH] ds1337 4/4 Ladislav Michl
2005-05-19  6:25                                   ` Ladislav Michl
2005-04-08 11:08                                   ` Jean Delvare
2005-05-19  6:25                                     ` Jean Delvare
2005-04-08 12:35                                     ` Ladislav Michl
2005-05-19  6:25                                       ` Ladislav Michl
2005-04-08 16:21                                       ` Jean Delvare
2005-05-19  6:25                                         ` Jean Delvare
2005-04-08 17:44                                       ` James Chapman
2005-05-19  6:25                                         ` James Chapman
2005-04-10 19:51                                         ` Ladislav Michl
2005-05-19  6:25                                           ` Ladislav Michl
2005-04-10 21:10                                           ` Jean Delvare
2005-05-19  6:25                                             ` Jean Delvare
2005-04-12 18:10                                             ` James Chapman
2005-05-19  6:25                                               ` James Chapman
2005-04-13 11:04                                               ` Ladislav Michl
2005-05-19  6:25                                                 ` Ladislav Michl
2005-04-13 19:02                                                 ` James Chapman
2005-05-19  6:25                                                   ` James Chapman
2005-04-13 19:48                                                   ` Ladislav Michl
2005-05-19  6:25                                                     ` Ladislav Michl
2005-05-19  6:25                                   ` Jean Delvare
2005-04-07 21:29                               ` [PATCH] i2c: new driver for ds1337 RTC Jean Delvare
2005-05-19  6:25                                 ` Jean Delvare
2005-04-07 23:16                                 ` Ladislav Michl
2005-05-19  6:25                                   ` Ladislav Michl

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=11123113902683@kroah.com \
    --to=gregkh@suse.de \
    --cc=khali@linux-fr.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sensors@Stimpy.netroedge.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.