linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] Various intel small device drivers
@ 2010-04-14 12:51 Alan Cox
  2010-04-14 12:51 ` [PATCH 1/4] hmc6352: Add driver for the HMC6352 compass Alan Cox
                   ` (3 more replies)
  0 siblings, 4 replies; 24+ messages in thread
From: Alan Cox @ 2010-04-14 12:51 UTC (permalink / raw)
  To: linux-i2c, khali, linux-input, linux-kernel

These have been through my clean up processing, in particular the accelerometers
are now using the input layer infrastructure.


---

Kalhan Trisal (4):
      emc1403: thermal sensor support
      liss331d1: accelerometer driver
      isl29020: ambient light sensor
      hmc6352: Add driver for the HMC6352 compass


 drivers/hwmon/Kconfig    |   34 ++++
 drivers/hwmon/Makefile   |    4 
 drivers/hwmon/emc1403.c  |  437 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/hwmon/hmc6352.c  |  235 +++++++++++++++++++++++++
 drivers/hwmon/isl29020.c |  243 ++++++++++++++++++++++++++
 drivers/hwmon/lis331dl.c |  286 ++++++++++++++++++++++++++++++
 6 files changed, 1239 insertions(+), 0 deletions(-)
 create mode 100644 drivers/hwmon/emc1403.c
 create mode 100644 drivers/hwmon/hmc6352.c
 create mode 100644 drivers/hwmon/isl29020.c
 create mode 100644 drivers/hwmon/lis331dl.c

-- 

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 1/4] hmc6352: Add driver for the HMC6352 compass
  2010-04-14 12:51 [PATCH 0/4] Various intel small device drivers Alan Cox
@ 2010-04-14 12:51 ` Alan Cox
       [not found]   ` <20100414125136.23181.16788.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
  2010-04-14 12:51 ` [PATCH 2/4] isl29020: ambient light sensor Alan Cox
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 24+ messages in thread
From: Alan Cox @ 2010-04-14 12:51 UTC (permalink / raw)
  To: linux-i2c, khali, linux-input, linux-kernel

From: Kalhan Trisal <kalhan.trisal@intel.com>

This driver will report the heading values in degrees to the sysfs interface.
The values returned are headings . e.g. 245.6

(Some cleanups from Alan Cox)

Signed-off-by: Kalhan Trisal <kalhan.trisal@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/hwmon/Kconfig   |    7 +
 drivers/hwmon/Makefile  |    1 
 drivers/hwmon/hmc6352.c |  235 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 243 insertions(+), 0 deletions(-)
 create mode 100644 drivers/hwmon/hmc6352.c


diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index d38447f..74f672d 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1088,6 +1088,13 @@ config SENSORS_MC13783_ADC
         help
           Support for the A/D converter on MC13783 PMIC.
 
+config SENSORS_HMC6352
+	tristate "Honeywell HMC6352 compass"
+	depends on I2C
+	help
+	  This driver provides support for the Honeywell HMC6352 compass,
+	  providing configuration and heading data via sysfs.
+
 if ACPI
 
 comment "ACPI drivers"
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 4aa1a3d..ad2ed36 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_SENSORS_GL518SM)	+= gl518sm.o
 obj-$(CONFIG_SENSORS_GL520SM)	+= gl520sm.o
 obj-$(CONFIG_SENSORS_ULTRA45)	+= ultra45_env.o
 obj-$(CONFIG_SENSORS_HDAPS)	+= hdaps.o
+obj-$(CONFIG_SENSORS_HMC6352)	+= hmc6352.o
 obj-$(CONFIG_SENSORS_I5K_AMB)	+= i5k_amb.o
 obj-$(CONFIG_SENSORS_IBMAEM)	+= ibmaem.o
 obj-$(CONFIG_SENSORS_IBMPEX)	+= ibmpex.o
diff --git a/drivers/hwmon/hmc6352.c b/drivers/hwmon/hmc6352.c
new file mode 100644
index 0000000..926982f
--- /dev/null
+++ b/drivers/hwmon/hmc6352.c
@@ -0,0 +1,235 @@
+/*
+ * hmc6352.c - Honeywell Compass Driver
+ *
+ * Copyright (C) 2009 Intel Corp
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+
+struct compass_data {
+	struct device *hwmon_dev;
+};
+
+static ssize_t compass_calibration_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret;
+	unsigned long val;
+	char  cmd[] = {0x43};
+	char  cmd1[] = {0x45};
+	struct i2c_msg msg[] = {
+		{ client->addr, 0, 1, cmd },
+	};
+	struct i2c_msg msg1[] = {
+		{ client->addr, 0, 1, cmd1 },
+	};
+
+	if (strict_strtoul(buf, 10, &val))
+		return -EINVAL;
+	if (val == 1) {
+		client->addr = 0x21;
+		ret = i2c_transfer(client->adapter, msg, 1);
+		if (ret != 1) {
+			dev_warn(dev, "hmc6352_comp : i2c callib start cmd failed\n");
+			return ret;
+		}
+	} else if (val == 2) {
+		client->addr = 0x21;
+		ret = i2c_transfer(client->adapter, msg1, 1);
+		if (ret != 1) {
+			dev_warn(dev, "hmc6352_comp : i2c callib stop cmd failed\n");
+			return ret;
+		}
+	} else
+		return -EINVAL;
+
+	return count;
+}
+
+static ssize_t compass_heading_data_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+
+	struct i2c_client *client = to_i2c_client(dev);
+	static char cmd[] = { 0x41 };
+	unsigned char i2c_data[2];
+	unsigned int ret, ret_val;
+	struct i2c_msg msg[] = {
+		{ client->addr, 0, 1, cmd },
+	};
+	struct i2c_msg msg1[] = {
+		{ client->addr, I2C_M_RD, 2, i2c_data },
+	};
+
+	client->addr = 0x21;
+	ret = i2c_transfer(client->adapter, msg, 1);
+	if (ret != 1) {
+		dev_warn(dev, "hmc6352 : i2c cmd  0x41 failed\n");
+		return ret;
+	}
+	msleep(10); /* sending 0x41 cmd we need to wait for 7-10 milli second*/
+	ret = i2c_transfer(client->adapter, msg1, 1);
+	if (ret != 1) {
+		dev_warn(dev, "hmc6352 : i2c read data cmd failed\n");
+		return ret;
+	}
+	ret_val = i2c_data[0];
+	ret_val = ((ret_val << 8) | i2c_data[1]);
+	return sprintf(buf, "%d.%d\n", ret_val/10, ret_val%10);
+}
+
+static ssize_t compass_power_mode_store(struct device *dev,
+		struct device_attribute *attr, const  char *buf, size_t count)
+{
+
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned long val;
+	unsigned int ret;
+	static char cmd[] = { 0x53 };
+	static char cmd1[] = { 0x57 };
+	struct i2c_msg msg[] = {
+		{ client->addr, 0, 1, cmd },
+	};
+	struct i2c_msg msg1[] = {
+		{ client->addr, 0, 1, cmd1 },
+	};
+
+	if (strict_strtoul(buf, 10, &val))
+		return -EINVAL;
+
+	if (val == 0) {
+		ret = i2c_transfer(client->adapter, msg, 1);
+		if (ret != 1)
+			dev_warn(dev, "hmc6352: i2c cmd  sleep mode failed\n");
+	} else if (val == 1) {
+		ret = i2c_transfer(client->adapter, msg1, 1);
+		if (ret != 1)
+			dev_warn(dev, "hmc6352: i2c cmd active mode failed\n");
+	} else
+		return -EINVAL;
+
+	return count;
+}
+
+static DEVICE_ATTR(heading, S_IRUGO, compass_heading_data_show, NULL);
+static DEVICE_ATTR(calibration, S_IWUSR, NULL, compass_calibration_store);
+static DEVICE_ATTR(power_state, S_IWUSR, NULL, compass_power_mode_store);
+
+static struct attribute *mid_att_compass[] = {
+	&dev_attr_heading.attr,
+	&dev_attr_calibration.attr,
+	&dev_attr_power_state.attr,
+	NULL
+};
+
+static struct attribute_group m_compass_gr = {
+	.name = "hmc6352",
+	.attrs = mid_att_compass
+};
+
+static int  hmc6352_probe(struct i2c_client *client,
+					const struct i2c_device_id *id)
+{
+	int res;
+	struct compass_data *data;
+
+	data = kzalloc(sizeof(struct compass_data), GFP_KERNEL);
+	if (data == NULL) {
+		dev_err(&client->dev, "hmc6352: out of memory");
+		return -ENOMEM;
+	}
+	i2c_set_clientdata(client, data);
+
+	res = sysfs_create_group(&client->dev.kobj, &m_compass_gr);
+	if (res) {
+		dev_err(&client->dev, "hmc6352: device_create_file failed\n");
+		goto compass_error1;
+	}
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		res = PTR_ERR(data->hwmon_dev);
+		data->hwmon_dev = NULL;
+		dev_err(&client->dev, "hmc6352: fail to register hwmon device\n");
+		sysfs_remove_group(&client->dev.kobj, &m_compass_gr);
+		goto compass_error1;
+	}
+	dev_info(&client->dev, "%s HMC6352 compass chip found\n",
+		client->name);
+	return res;
+
+compass_error1:
+	i2c_set_clientdata(client, NULL);
+	kfree(data);
+	return res;
+}
+
+static int hmc6352_remove(struct i2c_client *client)
+{
+	struct compass_data *data = i2c_get_clientdata(client);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &m_compass_gr);
+	kfree(data);
+	return 0;
+}
+
+static struct i2c_device_id hmc6352_id[] = {
+	{ "i2c_compass", 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, hmc6352_id);
+
+static struct i2c_driver hmc6352_driver = {
+	.driver = {
+	.name = "hmc6352",
+	},
+	.probe = hmc6352_probe,
+	.remove = hmc6352_remove,
+	.id_table = hmc6352_id,
+};
+
+static int __init sensor_hmc6352_init(void)
+{
+	return i2c_add_driver(&hmc6352_driver);
+}
+
+static void  __exit sensor_hmc6352_exit(void)
+{
+	i2c_del_driver(&hmc6352_driver);
+}
+
+module_init(sensor_hmc6352_init);
+module_exit(sensor_hmc6352_exit);
+
+MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com");
+MODULE_DESCRIPTION("hmc6352 Compass Driver");
+MODULE_LICENSE("GPL v2");


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 2/4] isl29020: ambient light sensor
  2010-04-14 12:51 [PATCH 0/4] Various intel small device drivers Alan Cox
  2010-04-14 12:51 ` [PATCH 1/4] hmc6352: Add driver for the HMC6352 compass Alan Cox
@ 2010-04-14 12:51 ` Alan Cox
       [not found]   ` <20100414125147.23181.5817.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
  2010-04-14 12:52 ` [PATCH 4/4] emc1403: thermal sensor support Alan Cox
       [not found] ` <20100414124913.23181.75903.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
  3 siblings, 1 reply; 24+ messages in thread
From: Alan Cox @ 2010-04-14 12:51 UTC (permalink / raw)
  To: linux-i2c, khali, linux-input, linux-kernel

From: Kalhan Trisal <kalhan.trisal@intel.com>

The LS driver will read the latest Lux measurement based upon the
light brightness and will report the LUX output through sysfs interface.

Signed-off-by: Kalhan Trisal <kalhan.trisal@intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/hwmon/Kconfig    |    9 ++
 drivers/hwmon/Makefile   |    1 
 drivers/hwmon/isl29020.c |  243 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 253 insertions(+), 0 deletions(-)
 create mode 100644 drivers/hwmon/isl29020.c


diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 74f672d..1fa2533 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1095,6 +1095,15 @@ config SENSORS_HMC6352
 	  This driver provides support for the Honeywell HMC6352 compass,
 	  providing configuration and heading data via sysfs.
 
+config SENSORS_ISL29020
+	tristate "Intersil ISL29020 ALS"
+	depends on I2C
+	help
+	  If you say yes here you get support for the ALS Devices
+	  Ambient Light Sensor monitoring chip.
+	  Range values can be configured using sysfs.
+	  Lux data is accessible via sysfs.
+
 if ACPI
 
 comment "ACPI drivers"
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index ad2ed36..13d6832 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_SENSORS_HMC6352)	+= hmc6352.o
 obj-$(CONFIG_SENSORS_I5K_AMB)	+= i5k_amb.o
 obj-$(CONFIG_SENSORS_IBMAEM)	+= ibmaem.o
 obj-$(CONFIG_SENSORS_IBMPEX)	+= ibmpex.o
+obj-$(CONFIG_SENSORS_ISL29020)	+= isl29020.o
 obj-$(CONFIG_SENSORS_IT87)	+= it87.o
 obj-$(CONFIG_SENSORS_K8TEMP)	+= k8temp.o
 obj-$(CONFIG_SENSORS_K10TEMP)	+= k10temp.o
diff --git a/drivers/hwmon/isl29020.c b/drivers/hwmon/isl29020.c
new file mode 100644
index 0000000..458140d
--- /dev/null
+++ b/drivers/hwmon/isl29020.c
@@ -0,0 +1,243 @@
+/*
+ * isl29020.c - Intersil  ALS Driver
+ *
+ * Copyright (C) 2008 Intel Corp
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+
+
+#define ALS_MIN_RANGE_VAL 0
+#define ALS_MAX_RANGE_VAL 5
+
+struct als_data {
+	struct device *hwmon_dev;
+};
+
+static unsigned int i2c_write_current_data(struct i2c_client *client,
+					unsigned int reg, unsigned int value)
+{
+	int ret_val;
+
+	ret_val = i2c_smbus_write_byte_data(client, reg, value);
+	return ret_val;
+}
+
+static ssize_t als_sensing_range_show(struct device *dev,
+			struct device_attribute *attr,  char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int  val;
+
+	val = i2c_smbus_read_byte_data(client, 0x00);
+	return sprintf(buf, "%d000\n", 1 << (2 * (val & 3)));
+
+}
+
+static ssize_t als_lux_output_data_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned int ret_val, val;
+	unsigned long int lux, max_count;
+	int tempv1, tempv2;
+
+	max_count = 65535;
+	tempv1 = i2c_smbus_read_byte_data(client, 0x02); /* MSB data */
+	tempv2 = i2c_smbus_read_byte_data(client, 0x01); /* LSB data */
+	ret_val = tempv1;
+	ret_val = (ret_val << 8 | tempv2);
+	val = i2c_smbus_read_byte_data(client, 0x00);
+	lux = ((((1 << (2 * (val & 3))))*1000) * ret_val) / max_count;
+	return sprintf(buf, "%ld\n", lux);
+}
+
+static ssize_t als_sensing_range_store(struct device *dev,
+		struct device_attribute *attr, const  char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned int ret_val, set_val = 0;
+	unsigned long val;
+
+	if (strict_strtoul(buf, 10, &val))
+		return -EINVAL;
+	ret_val = i2c_smbus_read_byte_data(client, 0x00);
+	ret_val = ret_val & 0xFC; /*reset the bit before setting them */
+	if (val == 1)
+		set_val = (ret_val | 0x00); /* setting the 1:0  bit */
+	else if (val == 2)
+		set_val = (ret_val | 0x01);
+	else if (val == 3)
+		set_val = (ret_val | 0x02);
+	else if (val == 4)
+		set_val = (ret_val | 0x03);
+	else
+		goto invarg;
+	i2c_write_current_data(client, 0x00, set_val);
+	return count;
+invarg:
+	return -EINVAL;
+}
+
+static ssize_t als_power_status_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret_val;
+
+	ret_val = i2c_smbus_read_byte_data(client, 0x00);
+	ret_val = ret_val & 0x80;
+	if (ret_val == 0x80)
+		ret_val = 1;
+	return sprintf(buf, "%x", ret_val);
+}
+
+static ssize_t als_power_status_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned long val = 0;
+	char curr_val;
+
+	if (strict_strtoul(buf, 10, &val))
+		return -EINVAL;
+
+	curr_val = i2c_smbus_read_byte_data(client, 0x00);
+	if (val == 1)
+		curr_val = curr_val | 0x80;
+	else if (val == 0)
+		curr_val = curr_val & 0x7F;
+	else
+		return -EINVAL;
+	i2c_write_current_data(client, 0x00, curr_val);
+	return count;
+}
+
+static DEVICE_ATTR(sensing_range, S_IRUGO | S_IWUSR,
+	als_sensing_range_show, als_sensing_range_store);
+static DEVICE_ATTR(lux_output, S_IRUGO, als_lux_output_data_show, NULL);
+static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
+	als_power_status_show, als_power_status_store);
+
+static struct attribute *mid_att_als[] = {
+	&dev_attr_sensing_range.attr,
+	&dev_attr_lux_output.attr,
+	&dev_attr_power_state.attr,
+	NULL
+};
+
+static struct attribute_group m_als_gr = {
+	.name = "isl29020",
+	.attrs = mid_att_als
+};
+
+static void als_set_default_config(struct i2c_client *client)
+{
+	i2c_write_current_data(client, 0x00, 0xc0);
+}
+
+static int  isl29020_probe(struct i2c_client *client,
+					const struct i2c_device_id *id)
+{
+	int res;
+	struct als_data *data;
+
+	data = kzalloc(sizeof(struct als_data), GFP_KERNEL);
+	if (data == NULL) {
+		printk(KERN_WARNING " isl29020: out of memory");
+		return -ENOMEM;
+	}
+	i2c_set_clientdata(client, data);
+
+	res = sysfs_create_group(&client->dev.kobj, &m_als_gr);
+	if (res) {
+		printk(KERN_WARNING "isl29020: device create file failed!!\n");
+		goto als_error1;
+	}
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		res = PTR_ERR(data->hwmon_dev);
+		data->hwmon_dev = NULL;
+		sysfs_remove_group(&client->dev.kobj, &m_als_gr);
+		printk(KERN_ERR "isl29020:unable to register hwmon device\n");
+		goto als_error1;
+	}
+	dev_info(&client->dev, "%s isl29020: ALS chip found\n", client->name);
+	als_set_default_config(client);
+	return res;
+
+als_error1:
+	i2c_set_clientdata(client, NULL);
+	kfree(data);
+	return res;
+}
+
+static int isl29020_remove(struct i2c_client *client)
+{
+	struct als_data *data = i2c_get_clientdata(client);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &m_als_gr);
+	kfree(data);
+	return 0;
+}
+
+static struct i2c_device_id isl29020_id[] = {
+	{ "i2c_als", 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, isl29020_id);
+
+static struct i2c_driver isl29020_driver = {
+	.driver = {
+	.name = "isl29020",
+	},
+	.probe = isl29020_probe,
+	.remove = isl29020_remove,
+	.id_table = isl29020_id,
+};
+
+static int __init sensor_isl29020_init(void)
+{
+	return i2c_add_driver(&isl29020_driver);
+}
+
+static void  __exit sensor_isl29020_exit(void)
+{
+	i2c_del_driver(&isl29020_driver);
+}
+
+module_init(sensor_isl29020_init);
+module_exit(sensor_isl29020_exit);
+
+MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com");
+MODULE_DESCRIPTION("Intersil isl29020 ALS Driver");
+MODULE_LICENSE("GPL v2");

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 3/4] liss331d1: accelerometer driver
       [not found] ` <20100414124913.23181.75903.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
@ 2010-04-14 12:52   ` Alan Cox
  2010-04-14 22:12     ` Éric Piel
       [not found]     ` <20100414125155.23181.56610.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
  2010-04-14 13:30   ` [PATCH 0/4] Various intel small device drivers Jean Delvare
  1 sibling, 2 replies; 24+ messages in thread
From: Alan Cox @ 2010-04-14 12:52 UTC (permalink / raw)
  To: linux-i2c-u79uwXL29TY76Z2rM5mHXA, khali-PUYAD+kWke1g9hUCZPvPmw,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

From: Kalhan Trisal <kalhan.trisal-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

The acceleremeter driver reads the x,y,z coordinate registers and provides
the information to user through the input layer

Conversion to input device, clean up and porting of retry fixes needed
for AAVA done by Alan Cox.

Signed-off-by: Kalhan Trisal <kalhan.trisal-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Alan Cox <alan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---

 drivers/hwmon/Kconfig    |    8 +
 drivers/hwmon/Makefile   |    1 
 drivers/hwmon/lis331dl.c |  286 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 295 insertions(+), 0 deletions(-)
 create mode 100644 drivers/hwmon/lis331dl.c


diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 1fa2533..6868b9d 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1104,6 +1104,14 @@ config SENSORS_ISL29020
 	  Range values can be configured using sysfs.
 	  Lux data is accessible via sysfs.
 
+config SENSORS_LIS331DL
+	tristate "STMicroeletronics LIS331DL three-axis digital accelerometer"
+	depends on I2C
+	help
+	  If you say yes here you get support for the Accelerometer  Devices
+	  Device can be configured using sysfs.
+	  x y Z data can be   accessible via sysfs.
+
 if ACPI
 
 comment "ACPI drivers"
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 13d6832..ebeb2a2 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_SENSORS_K10TEMP)	+= k10temp.o
 obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o
 obj-$(CONFIG_SENSORS_LIS3_SPI)	+= lis3lv02d.o lis3lv02d_spi.o
 obj-$(CONFIG_SENSORS_LIS3_I2C)	+= lis3lv02d.o lis3lv02d_i2c.o
+obj-$(CONFIG_SENSORS_LIS331DL)	+= lis331dl.o
 obj-$(CONFIG_SENSORS_LM63)	+= lm63.o
 obj-$(CONFIG_SENSORS_LM70)	+= lm70.o
 obj-$(CONFIG_SENSORS_LM73)	+= lm73.o
diff --git a/drivers/hwmon/lis331dl.c b/drivers/hwmon/lis331dl.c
new file mode 100644
index 0000000..34009eb
--- /dev/null
+++ b/drivers/hwmon/lis331dl.c
@@ -0,0 +1,286 @@
+/*
+ * lis331dl.c - ST LIS331DL  Accelerometer Driver
+ *
+ * Copyright (C) 2009 Intel Corp
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+#include <linux/input-polldev.h>
+
+
+#define POLL_INTERVAL	50
+
+struct lis331dl {
+	struct input_polled_dev *idev;
+	struct i2c_client *client;
+	struct mutex update_lock;
+};
+
+static ssize_t data_rate_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int val;
+	int speed = 100;
+
+	val = i2c_smbus_read_byte_data(client, 0x20);
+	if (val & 0x80); /* 1= 400HZ 0= 100HZ */
+		speed = 400;
+	return sprintf(buf, "%d\n", speed);
+}
+
+static ssize_t power_mode_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int val;
+
+	val = i2c_smbus_read_byte_data(client, 0x20) & 0x40;
+	if (val == 0x40)
+		val = 1;
+	return sprintf(buf, "%d\n", val);
+}
+
+static int read_with_retries(struct i2c_client *client, int r)
+{
+	int retries;
+	int ret;
+	
+	for (retries = 0; retries < 5; retries++) {
+		ret = i2c_smbus_read_byte_data(client, r);
+		if (ret != -ETIMEDOUT)
+			break;
+		msleep(10);
+	}
+	return ret;
+}
+
+static void lis331dl_poll(struct input_polled_dev *idev)
+{
+	struct input_dev *input = idev->input;
+	struct lis331dl *data = idev->private;
+	int x, y, z;
+	struct i2c_client *client = data->client;
+
+	x = read_with_retries(client, 0x29);
+	y = read_with_retries(client, 0x2B);
+	z = read_with_retries(client, 0x2D);
+
+	input_report_abs(input, ABS_X, x);
+	input_report_abs(input, ABS_Y, y);
+	input_report_abs(input, ABS_Z, z);
+	input_sync(input);
+}
+
+static ssize_t data_rate_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lis331dl *data = i2c_get_clientdata(client);
+	unsigned int ret_val;
+	unsigned long val;
+
+	if (strict_strtoul(buf, 10, &val))
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+
+	ret_val = i2c_smbus_read_byte_data(client, 0x20);
+	ret_val &= 0x7F;
+
+	switch (val) {
+	case 400:
+		ret_val |= 0x80;
+	case 100:
+		i2c_smbus_write_byte_data(client, 0x20, ret_val);
+		break;
+	default:		
+		mutex_unlock(&data->update_lock);
+		return -EINVAL;
+	}
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t power_mode_store(struct device *dev,
+		struct device_attribute *attr, const  char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lis331dl *data = i2c_get_clientdata(client);
+	unsigned int ret_val;
+	unsigned long val;
+
+	if (strict_strtoul(buf, 10, &val))
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+
+	ret_val = i2c_smbus_read_byte_data(client, 0x20);
+	ret_val &= 0xBF;
+	
+	switch(val) {
+	case 1:
+		ret_val |= 0x40;
+	case 0:
+		i2c_smbus_write_byte_data(client, 0x20, ret_val);
+		break;
+	default:
+		mutex_unlock(&data->update_lock);
+		return -EINVAL;
+	}
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static DEVICE_ATTR(data_rate, S_IRUGO | S_IWUSR,
+	data_rate_show, data_rate_store);
+static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
+	power_mode_show, power_mode_store);
+
+static struct attribute *mid_att_accelero[] = {
+	&dev_attr_data_rate.attr,
+	&dev_attr_power_state.attr,
+	NULL
+};
+
+static struct attribute_group m_accelero_gr = {
+	.name = "lis331dl",
+	.attrs = mid_att_accelero
+};
+
+static void accel_set_default_config(struct i2c_client *client)
+{
+	i2c_smbus_write_byte_data(client, 0x20, 0x47);
+}
+
+static int  lis331dl_probe(struct i2c_client *client,
+					const struct i2c_device_id *id)
+{
+	int res;
+	struct lis331dl *data;
+	struct input_polled_dev *idev;
+	struct input_dev *input;
+
+	data = kzalloc(sizeof(struct lis331dl), GFP_KERNEL);
+	if (data == NULL) {
+		dev_err(&client->dev, "lis331dl: out of memory\n");
+		return -ENOMEM;
+	}
+	mutex_init(&data->update_lock);
+	i2c_set_clientdata(client, data);
+	data->client = client;
+
+	res = sysfs_create_group(&client->dev.kobj, &m_accelero_gr);
+	if (res) {
+		dev_err(&client->dev, "lis331dl: sysfs  group failed\n");
+		goto accelero_error1;
+	}
+	idev = input_allocate_polled_device();
+	if (!idev) {
+		res = -ENOMEM;
+		dev_err(&client->dev,
+			"lis331dl: unable to register input device\n");
+		goto accelero_error2;
+	}
+	idev->poll = lis331dl_poll;
+	idev->poll_interval = POLL_INTERVAL;
+
+	idev->private = data;
+	data->idev =  idev;
+
+	input = idev->input;
+	input->name = "lis331dl";
+	input->phys = "lis331dl/input0";
+	input->id.bustype = BUS_I2C;
+	input->dev.parent = &client->dev;
+	input->evbit[0] = BIT_MASK(EV_ABS);
+	input_set_abs_params(input, ABS_X, 0, 255, 2, 2);
+	input_set_abs_params(input, ABS_Y, 0, 255, 2, 2);
+	input_set_abs_params(input, ABS_Z, 0, 255, 2, 2);
+
+	res = input_register_polled_device(idev);
+	if (res == 0) {
+		dev_info(&client->dev,
+			"%s lis331dl:  Accelerometer chip found",
+							client->name);
+		return 0;
+	}
+	input_free_polled_device(idev);
+accelero_error2:
+	sysfs_remove_group(&client->dev.kobj, &m_accelero_gr);
+accelero_error1:
+	i2c_set_clientdata(client, NULL);
+	kfree(data);
+	return res;
+}
+
+static int lis331dl_remove(struct i2c_client *client)
+{
+	struct lis331dl *data = i2c_get_clientdata(client);
+
+	input_unregister_polled_device(data->idev);
+	input_free_polled_device(data->idev);
+	sysfs_remove_group(&client->dev.kobj, &m_accelero_gr);
+	kfree(data);
+	return 0;
+}
+
+static struct i2c_device_id lis331dl_id[] = {
+	{ "i2c_accel", 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, lis331dl_id);
+
+static struct i2c_driver lis331dl_driver = {
+	.driver = {
+	.name = "lis331dl",
+	},
+	.probe = lis331dl_probe,
+	.remove = lis331dl_remove,
+	.id_table = lis331dl_id,
+};
+
+static int __init sensor_lis331dl_init(void)
+{
+	int res;
+
+	res = i2c_add_driver(&lis331dl_driver);
+	return res;
+}
+
+static void  __exit sensor_lis331dl_exit(void)
+{
+	i2c_del_driver(&lis331dl_driver);
+}
+
+module_init(sensor_lis331dl_init);
+module_exit(sensor_lis331dl_exit);
+
+MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>, Alan Cox");
+MODULE_DESCRIPTION("STMicroelectronics LIS331DL Accelerometer Driver");
+MODULE_LICENSE("GPL v2");

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 4/4] emc1403: thermal sensor support
  2010-04-14 12:51 [PATCH 0/4] Various intel small device drivers Alan Cox
  2010-04-14 12:51 ` [PATCH 1/4] hmc6352: Add driver for the HMC6352 compass Alan Cox
  2010-04-14 12:51 ` [PATCH 2/4] isl29020: ambient light sensor Alan Cox
@ 2010-04-14 12:52 ` Alan Cox
       [not found] ` <20100414124913.23181.75903.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
  3 siblings, 0 replies; 24+ messages in thread
From: Alan Cox @ 2010-04-14 12:52 UTC (permalink / raw)
  To: linux-i2c, khali, linux-input, linux-kernel

From: Kalhan Trisal <kalhan.trisal at intel.com>

Provides support for the emc1403 thermal sensor. Only reporting of values
is supported. The various Moorestown specific extras to do with thermal
alerts and the like are not in this version of the driver.

Signed-off-by: Kalhan Trisal <kalhan.trisal at intel.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
---

 drivers/hwmon/Kconfig   |   10 +
 drivers/hwmon/Makefile  |    1 
 drivers/hwmon/emc1403.c |  437 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 448 insertions(+), 0 deletions(-)
 create mode 100644 drivers/hwmon/emc1403.c


diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 6868b9d..34ee302 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1112,6 +1112,16 @@ config SENSORS_LIS331DL
 	  Device can be configured using sysfs.
 	  x y Z data can be   accessible via sysfs.
 
+config SENSORS_EMC1403
+	tristate "SMSC EMC1403 thermal sensor"
+	depends on I2C
+	help
+	  If you say yes here you get support for the SMSC Devices
+	  EMC1403 temperature monitoring chip.
+
+	  Threshold values can be configured using sysfs.
+	  Data from the different diode are accessible via sysfs.
+
 if ACPI
 
 comment "ACPI drivers"
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index ebeb2a2..a7332ce 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_SENSORS_ATXP1)	+= atxp1.o
 obj-$(CONFIG_SENSORS_CORETEMP)	+= coretemp.o
 obj-$(CONFIG_SENSORS_DME1737)	+= dme1737.o
 obj-$(CONFIG_SENSORS_DS1621)	+= ds1621.o
+obj-$(CONFIG_SENSORS_EMC1403)	+= emc1403.o
 obj-$(CONFIG_SENSORS_F71805F)	+= f71805f.o
 obj-$(CONFIG_SENSORS_F71882FG)	+= f71882fg.o
 obj-$(CONFIG_SENSORS_F75375S)	+= f75375s.o
diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c
new file mode 100644
index 0000000..b71cfa1
--- /dev/null
+++ b/drivers/hwmon/emc1403.c
@@ -0,0 +1,437 @@
+/*
+ * emc1403.c - SMSC Thermal Driver
+ *
+ * Copyright (C) 2008 Intel Corp
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * 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.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+
+
+/* Limit status reg Therm/High/Low/Fault*/
+static const u8 THM_STAT_REG_TEMP[] = { 0x37, 0x35, 0x36, 0x1B, 0x02};
+
+/* Channel  diode temp set */
+static const u8 THM_CHAN_TEMP[] = { 0x10, 0x08, 0x04, 0x02, 0x01 };
+
+/* Therm Limit reg store values */
+static const u8 THM_LIMIT_REG_TEMP[] = { 0x05, 0x06, 0x07, 0x08, 0x15, 0x16,
+						0x19, 0x1A, 0x20, 0x21 };
+
+/* DATA REGISTERS */
+static const u8 THM_REG_CURR_TEMP[] = { 0x00, 0x01, 0x23 };
+
+#define THERMAL_PID_REG		0xfd
+#define THERMAL_SMSC_ID_REG	0xfe
+#define THERMAL_REVISION_REG	0xff
+#define THERMAL_ADC_UPDATE_BUSY	0x80
+#define I2C_THERMAL_SLAVE_ADDR	0x4C
+#define TEMP1			1
+#define TEMP2			2
+#define TEMP3			4
+#define IRQ_TYPE_MASK		(1 << 15)
+#define HIGH_EVENT		1
+#define LOW_EVENT		2
+#define THERM_EVENT		3
+#define FAULT_EVENT		4
+#define ALERT_EVENT		1
+
+struct thermal_data {
+	struct i2c_client *client;
+	struct device *hwmon_dev;
+	int therm_irq;
+	int alert_irq;
+	struct work_struct therm_handler;
+	struct work_struct alert_handler;
+};
+
+static int calculate_offset(int type, int temp_ofs)
+{
+	int offset = 0;
+
+	switch (type) {
+	case TEMP1:
+		if (temp_ofs == 0)
+			offset = 1;
+		else if (temp_ofs == 1)
+			offset = 0;
+		else if (temp_ofs == 2)
+			offset = 8;
+		break;
+	case TEMP2:
+		if (temp_ofs == 0)
+			offset = 3;
+		else if (temp_ofs == 1)
+			offset = 2;
+		else if (temp_ofs == 2)
+			offset = 6;
+		break;
+	case TEMP3:
+		if (temp_ofs == 0)
+			offset = 5;
+		else if (temp_ofs == 1)
+			offset = 4;
+		else if (temp_ofs == 2)
+			offset = 7;
+		break;
+	default:
+		offset = -1;
+		break;
+	}
+	return offset;
+
+}
+
+
+static ssize_t show_temp_auto_offset(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct sensor_device_attribute_2 *s_attr = to_sensor_dev_attr_2(attr);
+	int temp_index = s_attr->index;
+	int temp_ofs = s_attr->nr;
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret_val;
+	int ret_offset;
+
+	ret_offset = calculate_offset(temp_index, temp_ofs);
+	if (ret_offset == -1)
+		return -EINVAL;
+	ret_val = i2c_smbus_read_byte_data(client,
+				THM_LIMIT_REG_TEMP[ret_offset]);
+	return sprintf(buf, "%d\n", ret_val);
+}
+
+static ssize_t store_temp_auto_offset(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *s_attr = to_sensor_dev_attr_2(attr);
+	int temp_index = s_attr->index;
+	int temp_ofs = s_attr->nr;
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned long val;
+	int ret_offset;
+
+	if (strict_strtoul(buf, 10, &val))
+		return -EINVAL;
+	ret_offset = calculate_offset(temp_index, temp_ofs);
+	if (ret_offset == -1)
+		return -EINVAL;
+
+	i2c_smbus_write_byte_data(client, THM_LIMIT_REG_TEMP[ret_offset], val);
+	return count;
+}
+
+static ssize_t show_temp_hyst(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	return sprintf(buf, "%d\n",
+		i2c_smbus_read_byte_data(client, THM_LIMIT_REG_TEMP[9]));
+}
+
+static ssize_t store_temp_hyst(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned long val;
+
+	if (strict_strtoul(buf, 10, &val))
+		return -EINVAL;
+	i2c_smbus_write_byte_data(client, THM_LIMIT_REG_TEMP[9], val);
+	return count;
+}
+
+static ssize_t show_temp1_curr_temp(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret_val;
+
+	ret_val = i2c_smbus_read_byte_data(client, THM_REG_CURR_TEMP[0]);
+	return sprintf(buf, "%d\n", ret_val);
+}
+
+static ssize_t show_temp2_curr_temp(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret_val;
+
+	ret_val = i2c_smbus_read_byte_data(client, THM_REG_CURR_TEMP[1]);
+	return sprintf(buf, "%d\n", ret_val);
+}
+
+static ssize_t show_temp3_curr_temp(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret_val;
+
+	ret_val = i2c_smbus_read_byte_data(client, THM_REG_CURR_TEMP[2]);
+	return sprintf(buf, "%d\n", ret_val);
+}
+
+static ssize_t show_status_reg(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int r1, r2, r3, r4;
+
+	r1 = i2c_smbus_read_byte_data(client, 0x1F);
+	r2 = i2c_smbus_read_byte_data(client, 0x35);
+	r3 = i2c_smbus_read_byte_data(client, 0x36);
+	r4 = i2c_smbus_read_byte_data(client, 0x37);
+	return sprintf(buf, "alarm=%x,High=%x,Low=%x,Therm=%x \n",
+				r1, r2, r3, r4);
+}
+
+static ssize_t show_power_state(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret_val = i2c_smbus_read_byte_data(client, 0x03);
+	return sprintf(buf, "%x", (ret_val >> 6) & 1);
+}
+
+static ssize_t store_power_state(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned long val;
+	char curr_val;
+
+	if (strict_strtoul(buf, 10, &val))
+		return -EINVAL;
+
+	curr_val = i2c_smbus_read_byte_data(client, 0x03);
+	if (val == 1)
+		curr_val &= 0xBF;
+	else if (val == 0)
+		curr_val |= 0x40;
+	else
+		return -EINVAL;
+	i2c_smbus_write_byte_data(client, 0x03, curr_val);
+	return count;
+}
+
+static ssize_t show_mode(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret_val = i2c_smbus_read_byte_data(client, 0x03);
+	return sprintf(buf, "%x", (ret_val >> 7) & 1);
+}
+
+static ssize_t store_mode(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned long val;
+	int curr_val;
+
+	if (strict_strtoul(buf, 10, &val))
+		return -EINVAL;
+
+	curr_val = i2c_smbus_read_byte_data(client, 0x03);
+	if (val == 1)
+		curr_val &= 0x7F;
+	else if (val == 0)
+		curr_val |= 0x80;
+	else
+		return -EINVAL;
+	i2c_smbus_write_byte_data(client, 0x03, curr_val);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR,
+	show_temp_auto_offset, store_temp_auto_offset, 0, 1);
+static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR,
+	show_temp_auto_offset, store_temp_auto_offset, 1, 1);
+static SENSOR_DEVICE_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR,
+	show_temp_auto_offset, store_temp_auto_offset, 2, 1);
+static DEVICE_ATTR(temp1_curr, S_IRUGO, show_temp1_curr_temp, NULL);
+
+static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR,
+	show_temp_auto_offset, store_temp_auto_offset, 0, 2);
+static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR,
+	show_temp_auto_offset, store_temp_auto_offset, 1, 2);
+static SENSOR_DEVICE_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR,
+	show_temp_auto_offset, store_temp_auto_offset, 2, 2);
+static DEVICE_ATTR(temp2_curr, S_IRUGO, show_temp2_curr_temp, NULL);
+
+static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR,
+	show_temp_auto_offset, store_temp_auto_offset, 0, 4);
+static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR,
+	show_temp_auto_offset, store_temp_auto_offset, 1, 4);
+static SENSOR_DEVICE_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR,
+	show_temp_auto_offset, store_temp_auto_offset, 2, 4);
+static DEVICE_ATTR(temp3_curr, S_IRUGO, show_temp3_curr_temp, NULL);
+
+static DEVICE_ATTR(hyster, S_IRUGO | S_IWUSR, show_temp_hyst, store_temp_hyst);
+static DEVICE_ATTR(status, S_IRUGO, show_status_reg, NULL);
+
+static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
+	show_power_state, store_power_state);
+static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, show_mode, store_mode);
+
+static struct attribute *mid_att_thermal[] = {
+	&sensor_dev_attr_temp1_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit.dev_attr.attr,
+	&dev_attr_temp1_curr.attr,
+	&sensor_dev_attr_temp2_min.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit.dev_attr.attr,
+	&dev_attr_temp2_curr.attr,
+	&sensor_dev_attr_temp3_min.dev_attr.attr,
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_crit.dev_attr.attr,
+	&dev_attr_temp3_curr.attr,
+	&dev_attr_hyster.attr,
+	&dev_attr_status.attr,
+	&dev_attr_power_state.attr,
+	&dev_attr_mode.attr,
+	NULL
+};
+
+static struct attribute_group m_thermal_gr = {
+	.name = "emc1403",
+	.attrs = mid_att_thermal
+};
+
+static void emc1403_set_default_config(struct i2c_client *client)
+{
+	i2c_smbus_write_byte_data(client, 0x03, 0x00);
+	i2c_smbus_write_byte_data(client, 0x04, 0x02);
+	i2c_smbus_write_byte_data(client, 0x22, 0x00);
+}
+
+static int  emc1403_probe(struct i2c_client *new_client,
+			const struct i2c_device_id *id)
+{
+	int res = 0;
+	struct thermal_data *data;
+	u16 pid, smsc_id, revision;
+
+	data = kzalloc(sizeof(struct thermal_data), GFP_KERNEL);
+
+	if (data == NULL) {
+		printk(KERN_WARNING "emc1403: out of memory");
+		return -ENOMEM;
+	}
+	data->client = new_client;
+	i2c_set_clientdata(new_client, data);
+
+	/* Check if thermal chip is SMSC and EMC1403 */
+	smsc_id = i2c_smbus_read_byte_data(new_client,
+					THERMAL_SMSC_ID_REG);
+	if (smsc_id != 0x5d) {
+		printk(KERN_WARNING "emc1403: vendor id mismatch\n");
+		goto thermal_error1;
+	}
+	pid = i2c_smbus_read_byte_data(new_client, THERMAL_PID_REG);
+	if (pid != 0x21)  {
+		printk(KERN_WARNING "emc1403: product id mismatch\n");
+		goto thermal_error1;
+	}
+	revision = i2c_smbus_read_byte_data(new_client,
+				THERMAL_REVISION_REG);
+	if (revision != 0x01) {
+		printk(KERN_WARNING "emc1403: rev id mismatch (is %d)\n",
+								revision);
+		goto thermal_error1;
+	}
+	res = sysfs_create_group(&new_client->dev.kobj, &m_thermal_gr);
+	if (res) {
+		printk(KERN_WARNING "emc1403: create group failed\n");
+		hwmon_device_unregister(data->hwmon_dev);
+		goto thermal_error1;
+	}
+	data->hwmon_dev = hwmon_device_register(&new_client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		res = PTR_ERR(data->hwmon_dev);
+		data->hwmon_dev = NULL;
+		printk(KERN_WARNING "emc1403:Register hwmon dev failed\n");
+		goto thermal_error2;
+	}
+	emc1403_set_default_config(new_client);
+	dev_info(&new_client->dev, "%s EMC1403 Thermal chip found\n",
+							new_client->name);
+	return res;
+thermal_error2:
+	sysfs_remove_group(&new_client->dev.kobj, &m_thermal_gr);
+thermal_error1:
+	i2c_set_clientdata(new_client, NULL);
+	kfree(data);
+	return res;
+}
+
+static int emc1403_remove(struct i2c_client *client)
+{
+	struct thermal_data *data = i2c_get_clientdata(client);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &m_thermal_gr);
+	kfree(data);
+	return 0;
+}
+
+static struct i2c_device_id emc1403_idtable[] = {
+	{ "i2c_thermal", 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, emc1403_idtable);
+
+static struct i2c_driver sensor_emc1403 = {
+	.driver = {
+		.name = "emc1403",
+	},
+	.probe = emc1403_probe,
+	.remove = emc1403_remove,
+	.id_table = emc1403_idtable,
+};
+
+static int __init sensor_emc1403_init(void)
+{
+	return i2c_add_driver(&sensor_emc1403);
+}
+
+static void  __exit sensor_emc1403_exit(void)
+{
+	i2c_del_driver(&sensor_emc1403);
+}
+
+module_init(sensor_emc1403_init);
+module_exit(sensor_emc1403_exit);
+
+MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com");
+MODULE_DESCRIPTION("emc1403 Thermal Driver");
+MODULE_LICENSE("GPL v2");


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH 0/4] Various intel small device drivers
       [not found] ` <20100414124913.23181.75903.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
  2010-04-14 12:52   ` [PATCH 3/4] liss331d1: accelerometer driver Alan Cox
@ 2010-04-14 13:30   ` Jean Delvare
       [not found]     ` <20100414153052.4e07f0cc-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
  1 sibling, 1 reply; 24+ messages in thread
From: Jean Delvare @ 2010-04-14 13:30 UTC (permalink / raw)
  To: Alan Cox
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

Hi Alan,

On Wed, 14 Apr 2010 13:51:30 +0100, Alan Cox wrote:
> These have been through my clean up processing, in particular the accelerometers
> are now using the input layer infrastructure.
> 
> 
> ---
> 
> Kalhan Trisal (4):
>       emc1403: thermal sensor support
>       liss331d1: accelerometer driver
>       isl29020: ambient light sensor
>       hmc6352: Add driver for the HMC6352 compass

The liss331d1, isl29020 and hmc6352 are not hardware monitoring drivers
and thus do not belong to drivers/hwmon.

BTW, when sending actual hardware monitoring drivers, the right mailing
list is lm-sensors, which you did not include. Please see MAINTAINERS.

>  drivers/hwmon/Kconfig    |   34 ++++
>  drivers/hwmon/Makefile   |    4 
>  drivers/hwmon/emc1403.c  |  437 ++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/hwmon/hmc6352.c  |  235 +++++++++++++++++++++++++
>  drivers/hwmon/isl29020.c |  243 ++++++++++++++++++++++++++
>  drivers/hwmon/lis331dl.c |  286 ++++++++++++++++++++++++++++++
>  6 files changed, 1239 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/hwmon/emc1403.c
>  create mode 100644 drivers/hwmon/hmc6352.c
>  create mode 100644 drivers/hwmon/isl29020.c
>  create mode 100644 drivers/hwmon/lis331dl.c
> 


-- 
Jean Delvare

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/4] hmc6352: Add driver for the HMC6352 compass
       [not found]   ` <20100414125136.23181.16788.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
@ 2010-04-14 13:48     ` Jonathan Cameron
       [not found]       ` <4BC5C7A8.1040807-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org>
  0 siblings, 1 reply; 24+ messages in thread
From: Jonathan Cameron @ 2010-04-14 13:48 UTC (permalink / raw)
  To: Alan Cox
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, khali-PUYAD+kWke1g9hUCZPvPmw,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA


Hi Alan, Kalhan, 

Couple of comments below.
On 04/14/10 13:51, Alan Cox wrote:
> From: Kalhan Trisal <kalhan.trisal-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> 
> This driver will report the heading values in degrees to the sysfs interface.
> The values returned are headings . e.g. 245.6
> 
> (Some cleanups from Alan Cox)
> 
> Signed-off-by: Kalhan Trisal <kalhan.trisal-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> Signed-off-by: Alan Cox <alan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
> ---
> 
>  drivers/hwmon/Kconfig   |    7 +
>  drivers/hwmon/Makefile  |    1 
>  drivers/hwmon/hmc6352.c |  235 +++++++++++++++++++++++++++++++++++++++++++++++
This is in no way a hwmon chip.  Surely misc is a better location for now
(pending the usual discussion about all singing all dancing sensors frameworks).

>  3 files changed, 243 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/hwmon/hmc6352.c
> 
> 
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index d38447f..74f672d 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -1088,6 +1088,13 @@ config SENSORS_MC13783_ADC
>          help
>            Support for the A/D converter on MC13783 PMIC.
>  
> +config SENSORS_HMC6352
> +	tristate "Honeywell HMC6352 compass"
> +	depends on I2C
> +	help
> +	  This driver provides support for the Honeywell HMC6352 compass,
> +	  providing configuration and heading data via sysfs.
> +
>  if ACPI
>  
>  comment "ACPI drivers"
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> index 4aa1a3d..ad2ed36 100644
> --- a/drivers/hwmon/Makefile
> +++ b/drivers/hwmon/Makefile
> @@ -49,6 +49,7 @@ obj-$(CONFIG_SENSORS_GL518SM)	+= gl518sm.o
>  obj-$(CONFIG_SENSORS_GL520SM)	+= gl520sm.o
>  obj-$(CONFIG_SENSORS_ULTRA45)	+= ultra45_env.o
>  obj-$(CONFIG_SENSORS_HDAPS)	+= hdaps.o
> +obj-$(CONFIG_SENSORS_HMC6352)	+= hmc6352.o
>  obj-$(CONFIG_SENSORS_I5K_AMB)	+= i5k_amb.o
>  obj-$(CONFIG_SENSORS_IBMAEM)	+= ibmaem.o
>  obj-$(CONFIG_SENSORS_IBMPEX)	+= ibmpex.o
> diff --git a/drivers/hwmon/hmc6352.c b/drivers/hwmon/hmc6352.c
> new file mode 100644
> index 0000000..926982f
> --- /dev/null
> +++ b/drivers/hwmon/hmc6352.c
> @@ -0,0 +1,235 @@
> +/*
> + * hmc6352.c - Honeywell Compass Driver
> + *
> + * Copyright (C) 2009 Intel Corp
> + *
> + *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + *
> + * 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.,
> + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/slab.h>
> +#include <linux/i2c.h>
> +#include <linux/hwmon.h>

Why these extra hwmon includes?  At least at first glance I can't see
any uses of them.  The only call to hwmon is to stick this in the
hwmon class.
> +#include <linux/hwmon-sysfs.h>
> +#include <linux/hwmon-vid.h>
> +#include <linux/err.h>
> +#include <linux/delay.h>
or any mutex usage?
> +#include <linux/mutex.h>
> +#include <linux/sysfs.h>
> +

I guess this makes the driver look like many others, but why bother with
the wrapping structure?  This is only used to keep track of the hwmon
device to be able to remove it later.
> +struct compass_data {
> +	struct device *hwmon_dev;
> +};
> +
> +static ssize_t compass_calibration_store(struct device *dev,
> +		struct device_attribute *attr, const char *buf, size_t count)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	int ret;
> +	unsigned long val;
Personally I'd have gone with a couple of chars then passed their address into
the i2c_msg initializations.  Guess it doesn't matter either way though!
> +	char  cmd[] = {0x43};
> +	char  cmd1[] = {0x45};
> +	struct i2c_msg msg[] = {
> +		{ client->addr, 0, 1, cmd },
> +	};
> +	struct i2c_msg msg1[] = {
> +		{ client->addr, 0, 1, cmd1 },
> +	};
> +
> +	if (strict_strtoul(buf, 10, &val))
> +		return -EINVAL;
> +	if (val == 1) {
These address changes looking a little unusual to me.  They may well be needed, but
if so can we have an explanatory comment?

> +		client->addr = 0x21;
> +		ret = i2c_transfer(client->adapter, msg, 1);
> +		if (ret != 1) {
> +			dev_warn(dev, "hmc6352_comp : i2c callib start cmd failed\n");
> +			return ret;
> +		}
> +	} else if (val == 2) {
> +		client->addr = 0x21;
> +		ret = i2c_transfer(client->adapter, msg1, 1);
> +		if (ret != 1) {
> +			dev_warn(dev, "hmc6352_comp : i2c callib stop cmd failed\n");
> +			return ret;
> +		}
> +	} else
> +		return -EINVAL;
> +
> +	return count;
> +}
> +
> +static ssize_t compass_heading_data_show(struct device *dev,
> +			struct device_attribute *attr, char *buf)
> +{
> +
> +	struct i2c_client *client = to_i2c_client(dev);
> +	static char cmd[] = { 0x41 };
> +	unsigned char i2c_data[2];
> +	unsigned int ret, ret_val;
> +	struct i2c_msg msg[] = {
> +		{ client->addr, 0, 1, cmd },
> +	};
> +	struct i2c_msg msg1[] = {
> +		{ client->addr, I2C_M_RD, 2, i2c_data },
> +	};
> +
> +	client->addr = 0x21;
> +	ret = i2c_transfer(client->adapter, msg, 1);
> +	if (ret != 1) {
> +		dev_warn(dev, "hmc6352 : i2c cmd  0x41 failed\n");
> +		return ret;
> +	}
> +	msleep(10); /* sending 0x41 cmd we need to wait for 7-10 milli second*/
> +	ret = i2c_transfer(client->adapter, msg1, 1);
> +	if (ret != 1) {
> +		dev_warn(dev, "hmc6352 : i2c read data cmd failed\n");
> +		return ret;
> +	}
> +	ret_val = i2c_data[0];
> +	ret_val = ((ret_val << 8) | i2c_data[1]);
> +	return sprintf(buf, "%d.%d\n", ret_val/10, ret_val%10);
> +}
> +
> +static ssize_t compass_power_mode_store(struct device *dev,
> +		struct device_attribute *attr, const  char *buf, size_t count)
> +{
> +
> +	struct i2c_client *client = to_i2c_client(dev);
> +	unsigned long val;
> +	unsigned int ret;
> +	static char cmd[] = { 0x53 };
> +	static char cmd1[] = { 0x57 };
> +	struct i2c_msg msg[] = {
> +		{ client->addr, 0, 1, cmd },
> +	};
> +	struct i2c_msg msg1[] = {
> +		{ client->addr, 0, 1, cmd1 },
> +	};
> +
> +	if (strict_strtoul(buf, 10, &val))
> +		return -EINVAL;
> +
> +	if (val == 0) {
> +		ret = i2c_transfer(client->adapter, msg, 1);
> +		if (ret != 1)
> +			dev_warn(dev, "hmc6352: i2c cmd  sleep mode failed\n");
> +	} else if (val == 1) {
> +		ret = i2c_transfer(client->adapter, msg1, 1);
> +		if (ret != 1)
> +			dev_warn(dev, "hmc6352: i2c cmd active mode failed\n");
> +	} else
> +		return -EINVAL;
> +
> +	return count;
> +}
> +
> +static DEVICE_ATTR(heading, S_IRUGO, compass_heading_data_show, NULL);
> +static DEVICE_ATTR(calibration, S_IWUSR, NULL, compass_calibration_store);
> +static DEVICE_ATTR(power_state, S_IWUSR, NULL, compass_power_mode_store);
> +
> +static struct attribute *mid_att_compass[] = {
> +	&dev_attr_heading.attr,
> +	&dev_attr_calibration.attr,
> +	&dev_attr_power_state.attr,
> +	NULL
> +};
> +
> +static struct attribute_group m_compass_gr = {
> +	.name = "hmc6352",
> +	.attrs = mid_att_compass
> +};
> +
> +static int  hmc6352_probe(struct i2c_client *client,
> +					const struct i2c_device_id *id)
> +{
> +	int res;
> +	struct compass_data *data;
> +
> +	data = kzalloc(sizeof(struct compass_data), GFP_KERNEL);
> +	if (data == NULL) {
> +		dev_err(&client->dev, "hmc6352: out of memory");
> +		return -ENOMEM;
> +	}
> +	i2c_set_clientdata(client, data);
> +
> +	res = sysfs_create_group(&client->dev.kobj, &m_compass_gr);
> +	if (res) {
> +		dev_err(&client->dev, "hmc6352: device_create_file failed\n");
> +		goto compass_error1;
> +	}
> +	data->hwmon_dev = hwmon_device_register(&client->dev);
> +	if (IS_ERR(data->hwmon_dev)) {
> +		res = PTR_ERR(data->hwmon_dev);
> +		data->hwmon_dev = NULL;
> +		dev_err(&client->dev, "hmc6352: fail to register hwmon device\n");
> +		sysfs_remove_group(&client->dev.kobj, &m_compass_gr);
> +		goto compass_error1;
> +	}
> +	dev_info(&client->dev, "%s HMC6352 compass chip found\n",
> +		client->name);
> +	return res;
> +
> +compass_error1:
> +	i2c_set_clientdata(client, NULL);
> +	kfree(data);
> +	return res;
> +}
> +
> +static int hmc6352_remove(struct i2c_client *client)
> +{
> +	struct compass_data *data = i2c_get_clientdata(client);
> +
> +	hwmon_device_unregister(data->hwmon_dev);
> +	sysfs_remove_group(&client->dev.kobj, &m_compass_gr);
> +	kfree(data);
> +	return 0;
> +}
> +

Why i2c_compass for the name? 
> +static struct i2c_device_id hmc6352_id[] = {
> +	{ "i2c_compass", 0 },
> +	{ }
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, hmc6352_id);
> +
> +static struct i2c_driver hmc6352_driver = {
> +	.driver = {
> +	.name = "hmc6352",
> +	},
> +	.probe = hmc6352_probe,
> +	.remove = hmc6352_remove,
> +	.id_table = hmc6352_id,
> +};
> +
> +static int __init _hmc6352_init(void)
> +{
> +	return i2c_add_driver(&hmc6352_driver);
> +}
> +
> +static void  __exit sensor_hmc6352_exit(void)
> +{
> +	i2c_del_driver(&hmc6352_driver);
> +}
> +
> +module_init(sensor_hmc6352_init);
> +module_exit(sensor_hmc6352_exit);
> +
> +MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org");
> +MODULE_DESCRIPTION("hmc6352 Compass Driver");
> +MODULE_LICENSE("GPL v2");
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 0/4] Various intel small device drivers
       [not found]     ` <20100414153052.4e07f0cc-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
@ 2010-04-14 13:49       ` Alan Cox
       [not found]         ` <20100414144912.12c83f51-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org>
  0 siblings, 1 reply; 24+ messages in thread
From: Alan Cox @ 2010-04-14 13:49 UTC (permalink / raw)
  To: Jean Delvare
  Cc: Alan Cox, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

> > Kalhan Trisal (4):
> >       emc1403: thermal sensor support
> >       liss331d1: accelerometer driver
> >       isl29020: ambient light sensor
> >       hmc6352: Add driver for the HMC6352 compass
> 
> The liss331d1, isl29020 and hmc6352 are not hardware monitoring drivers

Disagree somewhat. In fact on close grepping I find that there is another
related lis33 implementation in drivers/hwmon already 8)

Given all the accelerometers are in drivers/hwmon where do you think they
should be, and do you have pending patches to move the others ?

I'd also be interested where you think the compass fits if its not hwmon,
ditto the ambient light sensor ?

I'll bounce the emc1403 onto lm-sensors.

Thanks
Alan

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 0/4] Various intel small device drivers
       [not found]         ` <20100414144912.12c83f51-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org>
@ 2010-04-14 13:55           ` Jonathan Cameron
       [not found]             ` <4BC5C96B.7050901-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org>
  0 siblings, 1 reply; 24+ messages in thread
From: Jonathan Cameron @ 2010-04-14 13:55 UTC (permalink / raw)
  To: Alan Cox
  Cc: Jean Delvare, Alan Cox, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On 04/14/10 14:49, Alan Cox wrote:
>>> Kalhan Trisal (4):
>>>       emc1403: thermal sensor support
>>>       liss331d1: accelerometer driver
>>>       isl29020: ambient light sensor
>>>       hmc6352: Add driver for the HMC6352 compass
>>
>> The liss331d1, isl29020 and hmc6352 are not hardware monitoring drivers
> 
> Disagree somewhat. In fact on close grepping I find that there is another
> related lis33 implementation in drivers/hwmon already 8)
> 
> Given all the accelerometers are in drivers/hwmon where do you think they
> should be, and do you have pending patches to move the others ?
> 
> I'd also be interested where you think the compass fits if its not hwmon,
> ditto the ambient light sensor ?

If you like, feel free to (re)start an argument with Linus on the ambient light
sensor front.  Or see that thread for yet another round about discussion of
where these sensors should be. 

http://lkml.org/lkml/2010/3/1/367

Basically if it is primarily an input device for human interaction, see if
Dmitry is willing to take it into input (though note he may quite rightly
take some convincing!)

Otherwise, I'm happy to take more general sensors into IIO, but obviously that
is still in staging and evolving reasonably quickly at the moment (large number
of abi clean up patches half way through cleanup at the mo.)

Otherwise, misc with the intent to sweep them all up when an agreed upon
subsystem is in place.

> 
> I'll bounce the emc1403 onto lm-sensors.
> 
> Thanks
> Alan
> --
> To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 0/4] Various intel small device drivers
       [not found]             ` <4BC5C96B.7050901-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org>
@ 2010-04-14 14:19               ` Alan Cox
  0 siblings, 0 replies; 24+ messages in thread
From: Alan Cox @ 2010-04-14 14:19 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Jean Delvare, Alan Cox, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

> If you like, feel free to (re)start an argument with Linus on the ambient light
> sensor front.  Or see that thread for yet another round about discussion of
> where these sensors should be. 
> 
> http://lkml.org/lkml/2010/3/1/367
> 
> Basically if it is primarily an input device for human interaction, see if

Its a sensor on an embedded board, it might be managing the backlight or
measuring the dirt level in a sewage pipe depending upon application.

> Dmitry is willing to take it into input (though note he may quite rightly
> take some convincing!)

Its easy enough to make it an input device but that would then end up
with polled_input_dev which keeps waking up and costs battery. A lot of
the polled input model is somewhat broken in that regard but I can see
Linus point.

> Otherwise, misc with the intent to sweep them all up when an agreed upon
> subsystem is in place.

Looks like goes into misc for the moment with all the other light sensors
and I'll see if I can merge it with the 29007 support while I am at it.

Thanks

Alan

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/4] hmc6352: Add driver for the HMC6352 compass
       [not found]       ` <4BC5C7A8.1040807-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org>
@ 2010-04-14 14:32         ` Alan Cox
       [not found]           ` <20100414153234.22765666-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org>
  0 siblings, 1 reply; 24+ messages in thread
From: Alan Cox @ 2010-04-14 14:32 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Alan Cox, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	khali-PUYAD+kWke1g9hUCZPvPmw, linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

> This is in no way a hwmon chip.  Surely misc is a better location for now
> (pending the usual discussion about all singing all dancing sensors frameworks).

Yep it's moving at the moment


> > +#include <linux/module.h>
> > +#include <linux/init.h>
> > +#include <linux/slab.h>
> > +#include <linux/i2c.h>
> > +#include <linux/hwmon.h>
> 
> Why these extra hwmon includes?  At least at first glance I can't see
> any uses of them.  The only call to hwmon is to stick this in the
> hwmon class.

I inherited it for cleanup so these are good points (I've been staring at
piles of these for so long extra input is very useful - this is the tip
of the iceberg !)

> > +#include <linux/hwmon-sysfs.h>
> > +#include <linux/hwmon-vid.h>
> > +#include <linux/err.h>
> > +#include <linux/delay.h>
> or any mutex usage?
> > +#include <linux/mutex.h>
> > +#include <linux/sysfs.h>
> > +
> 
> I guess this makes the driver look like many others, but why bother with
> the wrapping structure?  This is only used to keep track of the hwmon
> device to be able to remove it later.

Should go - agreed will remove

> These address changes looking a little unusual to me.  They may well be needed, but
> if so can we have an explanatory comment?

Will investigate.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/4] hmc6352: Add driver for the HMC6352 compass
       [not found]           ` <20100414153234.22765666-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org>
@ 2010-04-14 14:51             ` Jonathan Cameron
  0 siblings, 0 replies; 24+ messages in thread
From: Jonathan Cameron @ 2010-04-14 14:51 UTC (permalink / raw)
  To: Alan Cox
  Cc: Jonathan Cameron, Alan Cox, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	khali-PUYAD+kWke1g9hUCZPvPmw, linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On 04/14/10 15:32, Alan Cox wrote:
>> This is in no way a hwmon chip.  Surely misc is a better location for now
>> (pending the usual discussion about all singing all dancing sensors frameworks).
> 
> Yep it's moving at the moment
> 
> 
>>> +#include <linux/module.h>
>>> +#include <linux/init.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/i2c.h>
>>> +#include <linux/hwmon.h>
>>
>> Why these extra hwmon includes?  At least at first glance I can't see
>> any uses of them.  The only call to hwmon is to stick this in the
>> hwmon class.
> 
> I inherited it for cleanup so these are good points (I've been staring at
> piles of these for so long extra input is very useful - this is the tip
> of the iceberg !)
Cool, post away.  Feel free to cc me in on anything in the category of general
sensors (accelerometers, magnetometers etc). If nothing else, I'm interested
to see them to get ideas for drivers in IIO etc.
> 
>>> +#include <linux/hwmon-sysfs.h>
>>> +#include <linux/hwmon-vid.h>
>>> +#include <linux/err.h>
>>> +#include <linux/delay.h>
>> or any mutex usage?
>>> +#include <linux/mutex.h>
>>> +#include <linux/sysfs.h>
>>> +
>>
>> I guess this makes the driver look like many others, but why bother with
>> the wrapping structure?  This is only used to keep track of the hwmon
>> device to be able to remove it later.
> 
> Should go - agreed will remove
> 
>> These address changes looking a little unusual to me.  They may well be needed, but
>> if so can we have an explanatory comment?
> 
> Will investigate.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 3/4] liss331d1: accelerometer driver
  2010-04-14 12:52   ` [PATCH 3/4] liss331d1: accelerometer driver Alan Cox
@ 2010-04-14 22:12     ` Éric Piel
       [not found]       ` <4BC63DC5.8040501-hGVxb2UgFK3z+pZb47iToQ@public.gmane.org>
  2010-04-15 10:28       ` Jonathan Cameron
       [not found]     ` <20100414125155.23181.56610.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
  1 sibling, 2 replies; 24+ messages in thread
From: Éric Piel @ 2010-04-14 22:12 UTC (permalink / raw)
  To: Alan Cox; +Cc: linux-i2c, khali, linux-input, linux-kernel

Op 14-04-10 14:52, Alan Cox schreef:
> From: Kalhan Trisal <kalhan.trisal@intel.com>
> 
> The acceleremeter driver reads the x,y,z coordinate registers and provides
> the information to user through the input layer
> 
> Conversion to input device, clean up and porting of retry fixes needed
> for AAVA done by Alan Cox.
Hello,

I wouldn't want to be too picky, if this driver works fine with your
hardware and it's tested, why not, but from looking at the spec of this
chip (and at the code of this driver), it looks like it could be
completely compatible with the lis3lv02d driver (with lis3lv02d_i2c).
Same registers, including the WHO_AM_I register which returns 0x3B
(which is a supported version).

Have you tried and there were some specific incompatibilities? To me, it
looks like the only thing not in the lis3lv02d is the read with multiple
retries, and it could be easily added if necessary for your hardware.

Cheers,
Eric


> 
> Signed-off-by: Kalhan Trisal <kalhan.trisal@intel.com>
> Signed-off-by: Alan Cox <alan@linux.intel.com>
> ---
> 
>  drivers/hwmon/Kconfig    |    8 +
>  drivers/hwmon/Makefile   |    1 
>  drivers/hwmon/lis331dl.c |  286 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 295 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/hwmon/lis331dl.c
> 
> 
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index 1fa2533..6868b9d 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -1104,6 +1104,14 @@ config SENSORS_ISL29020
>  	  Range values can be configured using sysfs.
>  	  Lux data is accessible via sysfs.
>  
> +config SENSORS_LIS331DL
> +	tristate "STMicroeletronics LIS331DL three-axis digital accelerometer"
> +	depends on I2C
> +	help
> +	  If you say yes here you get support for the Accelerometer  Devices
> +	  Device can be configured using sysfs.
> +	  x y Z data can be   accessible via sysfs.
> +
>  if ACPI
>  
>  comment "ACPI drivers"
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> index 13d6832..ebeb2a2 100644
> --- a/drivers/hwmon/Makefile
> +++ b/drivers/hwmon/Makefile
> @@ -60,6 +60,7 @@ obj-$(CONFIG_SENSORS_K10TEMP)	+= k10temp.o
>  obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o
>  obj-$(CONFIG_SENSORS_LIS3_SPI)	+= lis3lv02d.o lis3lv02d_spi.o
>  obj-$(CONFIG_SENSORS_LIS3_I2C)	+= lis3lv02d.o lis3lv02d_i2c.o
> +obj-$(CONFIG_SENSORS_LIS331DL)	+= lis331dl.o
>  obj-$(CONFIG_SENSORS_LM63)	+= lm63.o
>  obj-$(CONFIG_SENSORS_LM70)	+= lm70.o
>  obj-$(CONFIG_SENSORS_LM73)	+= lm73.o
> diff --git a/drivers/hwmon/lis331dl.c b/drivers/hwmon/lis331dl.c
> new file mode 100644
> index 0000000..34009eb
> --- /dev/null
> +++ b/drivers/hwmon/lis331dl.c
> @@ -0,0 +1,286 @@
> +/*
> + * lis331dl.c - ST LIS331DL  Accelerometer Driver
> + *
> + * Copyright (C) 2009 Intel Corp
> + *
> + *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + *
> + * 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.,
> + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/slab.h>
> +#include <linux/i2c.h>
> +#include <linux/err.h>
> +#include <linux/delay.h>
> +#include <linux/mutex.h>
> +#include <linux/sysfs.h>
> +#include <linux/input-polldev.h>
> +
> +
> +#define POLL_INTERVAL	50
> +
> +struct lis331dl {
> +	struct input_polled_dev *idev;
> +	struct i2c_client *client;
> +	struct mutex update_lock;
> +};
> +
> +static ssize_t data_rate_show(struct device *dev,
> +			struct device_attribute *attr, char *buf)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	int val;
> +	int speed = 100;
> +
> +	val = i2c_smbus_read_byte_data(client, 0x20);
> +	if (val & 0x80); /* 1= 400HZ 0= 100HZ */
> +		speed = 400;
> +	return sprintf(buf, "%d\n", speed);
> +}
> +
> +static ssize_t power_mode_show(struct device *dev,
> +			struct device_attribute *attr, char *buf)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	int val;
> +
> +	val = i2c_smbus_read_byte_data(client, 0x20) & 0x40;
> +	if (val == 0x40)
> +		val = 1;
> +	return sprintf(buf, "%d\n", val);
> +}
> +
> +static int read_with_retries(struct i2c_client *client, int r)
> +{
> +	int retries;
> +	int ret;
> +	
> +	for (retries = 0; retries < 5; retries++) {
> +		ret = i2c_smbus_read_byte_data(client, r);
> +		if (ret != -ETIMEDOUT)
> +			break;
> +		msleep(10);
> +	}
> +	return ret;
> +}
> +
> +static void lis331dl_poll(struct input_polled_dev *idev)
> +{
> +	struct input_dev *input = idev->input;
> +	struct lis331dl *data = idev->private;
> +	int x, y, z;
> +	struct i2c_client *client = data->client;
> +
> +	x = read_with_retries(client, 0x29);
> +	y = read_with_retries(client, 0x2B);
> +	z = read_with_retries(client, 0x2D);
> +
> +	input_report_abs(input, ABS_X, x);
> +	input_report_abs(input, ABS_Y, y);
> +	input_report_abs(input, ABS_Z, z);
> +	input_sync(input);
> +}
> +
> +static ssize_t data_rate_store(struct device *dev,
> +		struct device_attribute *attr, const char *buf, size_t count)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	struct lis331dl *data = i2c_get_clientdata(client);
> +	unsigned int ret_val;
> +	unsigned long val;
> +
> +	if (strict_strtoul(buf, 10, &val))
> +		return -EINVAL;
> +
> +	mutex_lock(&data->update_lock);
> +
> +	ret_val = i2c_smbus_read_byte_data(client, 0x20);
> +	ret_val &= 0x7F;
> +
> +	switch (val) {
> +	case 400:
> +		ret_val |= 0x80;
> +	case 100:
> +		i2c_smbus_write_byte_data(client, 0x20, ret_val);
> +		break;
> +	default:		
> +		mutex_unlock(&data->update_lock);
> +		return -EINVAL;
> +	}
> +	mutex_unlock(&data->update_lock);
> +	return count;
> +}
> +
> +static ssize_t power_mode_store(struct device *dev,
> +		struct device_attribute *attr, const  char *buf, size_t count)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	struct lis331dl *data = i2c_get_clientdata(client);
> +	unsigned int ret_val;
> +	unsigned long val;
> +
> +	if (strict_strtoul(buf, 10, &val))
> +		return -EINVAL;
> +
> +	mutex_lock(&data->update_lock);
> +
> +	ret_val = i2c_smbus_read_byte_data(client, 0x20);
> +	ret_val &= 0xBF;
> +	
> +	switch(val) {
> +	case 1:
> +		ret_val |= 0x40;
> +	case 0:
> +		i2c_smbus_write_byte_data(client, 0x20, ret_val);
> +		break;
> +	default:
> +		mutex_unlock(&data->update_lock);
> +		return -EINVAL;
> +	}
> +	mutex_unlock(&data->update_lock);
> +	return count;
> +}
> +
> +static DEVICE_ATTR(data_rate, S_IRUGO | S_IWUSR,
> +	data_rate_show, data_rate_store);
> +static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
> +	power_mode_show, power_mode_store);
> +
> +static struct attribute *mid_att_accelero[] = {
> +	&dev_attr_data_rate.attr,
> +	&dev_attr_power_state.attr,
> +	NULL
> +};
> +
> +static struct attribute_group m_accelero_gr = {
> +	.name = "lis331dl",
> +	.attrs = mid_att_accelero
> +};
> +
> +static void accel_set_default_config(struct i2c_client *client)
> +{
> +	i2c_smbus_write_byte_data(client, 0x20, 0x47);
> +}
> +
> +static int  lis331dl_probe(struct i2c_client *client,
> +					const struct i2c_device_id *id)
> +{
> +	int res;
> +	struct lis331dl *data;
> +	struct input_polled_dev *idev;
> +	struct input_dev *input;
> +
> +	data = kzalloc(sizeof(struct lis331dl), GFP_KERNEL);
> +	if (data == NULL) {
> +		dev_err(&client->dev, "lis331dl: out of memory\n");
> +		return -ENOMEM;
> +	}
> +	mutex_init(&data->update_lock);
> +	i2c_set_clientdata(client, data);
> +	data->client = client;
> +
> +	res = sysfs_create_group(&client->dev.kobj, &m_accelero_gr);
> +	if (res) {
> +		dev_err(&client->dev, "lis331dl: sysfs  group failed\n");
> +		goto accelero_error1;
> +	}
> +	idev = input_allocate_polled_device();
> +	if (!idev) {
> +		res = -ENOMEM;
> +		dev_err(&client->dev,
> +			"lis331dl: unable to register input device\n");
> +		goto accelero_error2;
> +	}
> +	idev->poll = lis331dl_poll;
> +	idev->poll_interval = POLL_INTERVAL;
> +
> +	idev->private = data;
> +	data->idev =  idev;
> +
> +	input = idev->input;
> +	input->name = "lis331dl";
> +	input->phys = "lis331dl/input0";
> +	input->id.bustype = BUS_I2C;
> +	input->dev.parent = &client->dev;
> +	input->evbit[0] = BIT_MASK(EV_ABS);
> +	input_set_abs_params(input, ABS_X, 0, 255, 2, 2);
> +	input_set_abs_params(input, ABS_Y, 0, 255, 2, 2);
> +	input_set_abs_params(input, ABS_Z, 0, 255, 2, 2);
> +
> +	res = input_register_polled_device(idev);
> +	if (res == 0) {
> +		dev_info(&client->dev,
> +			"%s lis331dl:  Accelerometer chip found",
> +							client->name);
> +		return 0;
> +	}
> +	input_free_polled_device(idev);
> +accelero_error2:
> +	sysfs_remove_group(&client->dev.kobj, &m_accelero_gr);
> +accelero_error1:
> +	i2c_set_clientdata(client, NULL);
> +	kfree(data);
> +	return res;
> +}
> +
> +static int lis331dl_remove(struct i2c_client *client)
> +{
> +	struct lis331dl *data = i2c_get_clientdata(client);
> +
> +	input_unregister_polled_device(data->idev);
> +	input_free_polled_device(data->idev);
> +	sysfs_remove_group(&client->dev.kobj, &m_accelero_gr);
> +	kfree(data);
> +	return 0;
> +}
> +
> +static struct i2c_device_id lis331dl_id[] = {
> +	{ "i2c_accel", 0 },
> +	{ }
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, lis331dl_id);
> +
> +static struct i2c_driver lis331dl_driver = {
> +	.driver = {
> +	.name = "lis331dl",
> +	},
> +	.probe = lis331dl_probe,
> +	.remove = lis331dl_remove,
> +	.id_table = lis331dl_id,
> +};
> +
> +static int __init sensor_lis331dl_init(void)
> +{
> +	int res;
> +
> +	res = i2c_add_driver(&lis331dl_driver);
> +	return res;
> +}
> +
> +static void  __exit sensor_lis331dl_exit(void)
> +{
> +	i2c_del_driver(&lis331dl_driver);
> +}
> +
> +module_init(sensor_lis331dl_init);
> +module_exit(sensor_lis331dl_exit);
> +
> +MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com>, Alan Cox");
> +MODULE_DESCRIPTION("STMicroelectronics LIS331DL Accelerometer Driver");
> +MODULE_LICENSE("GPL v2");
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 3/4] liss331d1: accelerometer driver
       [not found]       ` <4BC63DC5.8040501-hGVxb2UgFK3z+pZb47iToQ@public.gmane.org>
@ 2010-04-14 22:34         ` Daniel Mack
       [not found]           ` <20100414223429.GW30807-ahpEBR4enfnCULTFXS99ULNAH6kLmebB@public.gmane.org>
  2010-04-14 22:37         ` Alan Cox
  1 sibling, 1 reply; 24+ messages in thread
From: Daniel Mack @ 2010-04-14 22:34 UTC (permalink / raw)
  To: Éric Piel
  Cc: Alan Cox, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	khali-PUYAD+kWke1g9hUCZPvPmw, linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On Thu, Apr 15, 2010 at 12:12:21AM +0200, Éric Piel wrote:
> Op 14-04-10 14:52, Alan Cox schreef:
> > From: Kalhan Trisal <kalhan.trisal-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> > 
> > The acceleremeter driver reads the x,y,z coordinate registers and provides
> > the information to user through the input layer
> > 
> > Conversion to input device, clean up and porting of retry fixes needed
> > for AAVA done by Alan Cox.
> Hello,
> 
> I wouldn't want to be too picky, if this driver works fine with your
> hardware and it's tested, why not, but from looking at the spec of this
> chip (and at the code of this driver), it looks like it could be
> completely compatible with the lis3lv02d driver (with lis3lv02d_i2c).
> Same registers, including the WHO_AM_I register which returns 0x3B
> (which is a supported version).
> 
> Have you tried and there were some specific incompatibilities? To me, it
> looks like the only thing not in the lis3lv02d is the read with multiple
> retries, and it could be easily added if necessary for your hardware.

Yes, that would be better. Also because there's also a SPI version of
the lis331dl. If support for this chip would be incorporated in the
existing driver, they would automatically be supported as well.

Daniel


> > Signed-off-by: Kalhan Trisal <kalhan.trisal-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> > Signed-off-by: Alan Cox <alan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
> > ---
> > 
> >  drivers/hwmon/Kconfig    |    8 +
> >  drivers/hwmon/Makefile   |    1 
> >  drivers/hwmon/lis331dl.c |  286 ++++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 295 insertions(+), 0 deletions(-)
> >  create mode 100644 drivers/hwmon/lis331dl.c
> > 
> > 
> > diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> > index 1fa2533..6868b9d 100644
> > --- a/drivers/hwmon/Kconfig
> > +++ b/drivers/hwmon/Kconfig
> > @@ -1104,6 +1104,14 @@ config SENSORS_ISL29020
> >  	  Range values can be configured using sysfs.
> >  	  Lux data is accessible via sysfs.
> >  
> > +config SENSORS_LIS331DL
> > +	tristate "STMicroeletronics LIS331DL three-axis digital accelerometer"
> > +	depends on I2C
> > +	help
> > +	  If you say yes here you get support for the Accelerometer  Devices
> > +	  Device can be configured using sysfs.
> > +	  x y Z data can be   accessible via sysfs.
> > +
> >  if ACPI
> >  
> >  comment "ACPI drivers"
> > diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> > index 13d6832..ebeb2a2 100644
> > --- a/drivers/hwmon/Makefile
> > +++ b/drivers/hwmon/Makefile
> > @@ -60,6 +60,7 @@ obj-$(CONFIG_SENSORS_K10TEMP)	+= k10temp.o
> >  obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o
> >  obj-$(CONFIG_SENSORS_LIS3_SPI)	+= lis3lv02d.o lis3lv02d_spi.o
> >  obj-$(CONFIG_SENSORS_LIS3_I2C)	+= lis3lv02d.o lis3lv02d_i2c.o
> > +obj-$(CONFIG_SENSORS_LIS331DL)	+= lis331dl.o
> >  obj-$(CONFIG_SENSORS_LM63)	+= lm63.o
> >  obj-$(CONFIG_SENSORS_LM70)	+= lm70.o
> >  obj-$(CONFIG_SENSORS_LM73)	+= lm73.o
> > diff --git a/drivers/hwmon/lis331dl.c b/drivers/hwmon/lis331dl.c
> > new file mode 100644
> > index 0000000..34009eb
> > --- /dev/null
> > +++ b/drivers/hwmon/lis331dl.c
> > @@ -0,0 +1,286 @@
> > +/*
> > + * lis331dl.c - ST LIS331DL  Accelerometer Driver
> > + *
> > + * Copyright (C) 2009 Intel Corp
> > + *
> > + *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > + *
> > + * 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.,
> > + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
> > + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > + *
> > + */
> > +
> > +#include <linux/module.h>
> > +#include <linux/init.h>
> > +#include <linux/slab.h>
> > +#include <linux/i2c.h>
> > +#include <linux/err.h>
> > +#include <linux/delay.h>
> > +#include <linux/mutex.h>
> > +#include <linux/sysfs.h>
> > +#include <linux/input-polldev.h>
> > +
> > +
> > +#define POLL_INTERVAL	50
> > +
> > +struct lis331dl {
> > +	struct input_polled_dev *idev;
> > +	struct i2c_client *client;
> > +	struct mutex update_lock;
> > +};
> > +
> > +static ssize_t data_rate_show(struct device *dev,
> > +			struct device_attribute *attr, char *buf)
> > +{
> > +	struct i2c_client *client = to_i2c_client(dev);
> > +	int val;
> > +	int speed = 100;
> > +
> > +	val = i2c_smbus_read_byte_data(client, 0x20);
> > +	if (val & 0x80); /* 1= 400HZ 0= 100HZ */
> > +		speed = 400;
> > +	return sprintf(buf, "%d\n", speed);
> > +}
> > +
> > +static ssize_t power_mode_show(struct device *dev,
> > +			struct device_attribute *attr, char *buf)
> > +{
> > +	struct i2c_client *client = to_i2c_client(dev);
> > +	int val;
> > +
> > +	val = i2c_smbus_read_byte_data(client, 0x20) & 0x40;
> > +	if (val == 0x40)
> > +		val = 1;
> > +	return sprintf(buf, "%d\n", val);
> > +}
> > +
> > +static int read_with_retries(struct i2c_client *client, int r)
> > +{
> > +	int retries;
> > +	int ret;
> > +	
> > +	for (retries = 0; retries < 5; retries++) {
> > +		ret = i2c_smbus_read_byte_data(client, r);
> > +		if (ret != -ETIMEDOUT)
> > +			break;
> > +		msleep(10);
> > +	}
> > +	return ret;
> > +}
> > +
> > +static void lis331dl_poll(struct input_polled_dev *idev)
> > +{
> > +	struct input_dev *input = idev->input;
> > +	struct lis331dl *data = idev->private;
> > +	int x, y, z;
> > +	struct i2c_client *client = data->client;
> > +
> > +	x = read_with_retries(client, 0x29);
> > +	y = read_with_retries(client, 0x2B);
> > +	z = read_with_retries(client, 0x2D);
> > +
> > +	input_report_abs(input, ABS_X, x);
> > +	input_report_abs(input, ABS_Y, y);
> > +	input_report_abs(input, ABS_Z, z);
> > +	input_sync(input);
> > +}
> > +
> > +static ssize_t data_rate_store(struct device *dev,
> > +		struct device_attribute *attr, const char *buf, size_t count)
> > +{
> > +	struct i2c_client *client = to_i2c_client(dev);
> > +	struct lis331dl *data = i2c_get_clientdata(client);
> > +	unsigned int ret_val;
> > +	unsigned long val;
> > +
> > +	if (strict_strtoul(buf, 10, &val))
> > +		return -EINVAL;
> > +
> > +	mutex_lock(&data->update_lock);
> > +
> > +	ret_val = i2c_smbus_read_byte_data(client, 0x20);
> > +	ret_val &= 0x7F;
> > +
> > +	switch (val) {
> > +	case 400:
> > +		ret_val |= 0x80;
> > +	case 100:
> > +		i2c_smbus_write_byte_data(client, 0x20, ret_val);
> > +		break;
> > +	default:		
> > +		mutex_unlock(&data->update_lock);
> > +		return -EINVAL;
> > +	}
> > +	mutex_unlock(&data->update_lock);
> > +	return count;
> > +}
> > +
> > +static ssize_t power_mode_store(struct device *dev,
> > +		struct device_attribute *attr, const  char *buf, size_t count)
> > +{
> > +	struct i2c_client *client = to_i2c_client(dev);
> > +	struct lis331dl *data = i2c_get_clientdata(client);
> > +	unsigned int ret_val;
> > +	unsigned long val;
> > +
> > +	if (strict_strtoul(buf, 10, &val))
> > +		return -EINVAL;
> > +
> > +	mutex_lock(&data->update_lock);
> > +
> > +	ret_val = i2c_smbus_read_byte_data(client, 0x20);
> > +	ret_val &= 0xBF;
> > +	
> > +	switch(val) {
> > +	case 1:
> > +		ret_val |= 0x40;
> > +	case 0:
> > +		i2c_smbus_write_byte_data(client, 0x20, ret_val);
> > +		break;
> > +	default:
> > +		mutex_unlock(&data->update_lock);
> > +		return -EINVAL;
> > +	}
> > +	mutex_unlock(&data->update_lock);
> > +	return count;
> > +}
> > +
> > +static DEVICE_ATTR(data_rate, S_IRUGO | S_IWUSR,
> > +	data_rate_show, data_rate_store);
> > +static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
> > +	power_mode_show, power_mode_store);
> > +
> > +static struct attribute *mid_att_accelero[] = {
> > +	&dev_attr_data_rate.attr,
> > +	&dev_attr_power_state.attr,
> > +	NULL
> > +};
> > +
> > +static struct attribute_group m_accelero_gr = {
> > +	.name = "lis331dl",
> > +	.attrs = mid_att_accelero
> > +};
> > +
> > +static void accel_set_default_config(struct i2c_client *client)
> > +{
> > +	i2c_smbus_write_byte_data(client, 0x20, 0x47);
> > +}
> > +
> > +static int  lis331dl_probe(struct i2c_client *client,
> > +					const struct i2c_device_id *id)
> > +{
> > +	int res;
> > +	struct lis331dl *data;
> > +	struct input_polled_dev *idev;
> > +	struct input_dev *input;
> > +
> > +	data = kzalloc(sizeof(struct lis331dl), GFP_KERNEL);
> > +	if (data == NULL) {
> > +		dev_err(&client->dev, "lis331dl: out of memory\n");
> > +		return -ENOMEM;
> > +	}
> > +	mutex_init(&data->update_lock);
> > +	i2c_set_clientdata(client, data);
> > +	data->client = client;
> > +
> > +	res = sysfs_create_group(&client->dev.kobj, &m_accelero_gr);
> > +	if (res) {
> > +		dev_err(&client->dev, "lis331dl: sysfs  group failed\n");
> > +		goto accelero_error1;
> > +	}
> > +	idev = input_allocate_polled_device();
> > +	if (!idev) {
> > +		res = -ENOMEM;
> > +		dev_err(&client->dev,
> > +			"lis331dl: unable to register input device\n");
> > +		goto accelero_error2;
> > +	}
> > +	idev->poll = lis331dl_poll;
> > +	idev->poll_interval = POLL_INTERVAL;
> > +
> > +	idev->private = data;
> > +	data->idev =  idev;
> > +
> > +	input = idev->input;
> > +	input->name = "lis331dl";
> > +	input->phys = "lis331dl/input0";
> > +	input->id.bustype = BUS_I2C;
> > +	input->dev.parent = &client->dev;
> > +	input->evbit[0] = BIT_MASK(EV_ABS);
> > +	input_set_abs_params(input, ABS_X, 0, 255, 2, 2);
> > +	input_set_abs_params(input, ABS_Y, 0, 255, 2, 2);
> > +	input_set_abs_params(input, ABS_Z, 0, 255, 2, 2);
> > +
> > +	res = input_register_polled_device(idev);
> > +	if (res == 0) {
> > +		dev_info(&client->dev,
> > +			"%s lis331dl:  Accelerometer chip found",
> > +							client->name);
> > +		return 0;
> > +	}
> > +	input_free_polled_device(idev);
> > +accelero_error2:
> > +	sysfs_remove_group(&client->dev.kobj, &m_accelero_gr);
> > +accelero_error1:
> > +	i2c_set_clientdata(client, NULL);
> > +	kfree(data);
> > +	return res;
> > +}
> > +
> > +static int lis331dl_remove(struct i2c_client *client)
> > +{
> > +	struct lis331dl *data = i2c_get_clientdata(client);
> > +
> > +	input_unregister_polled_device(data->idev);
> > +	input_free_polled_device(data->idev);
> > +	sysfs_remove_group(&client->dev.kobj, &m_accelero_gr);
> > +	kfree(data);
> > +	return 0;
> > +}
> > +
> > +static struct i2c_device_id lis331dl_id[] = {
> > +	{ "i2c_accel", 0 },
> > +	{ }
> > +};
> > +
> > +MODULE_DEVICE_TABLE(i2c, lis331dl_id);
> > +
> > +static struct i2c_driver lis331dl_driver = {
> > +	.driver = {
> > +	.name = "lis331dl",
> > +	},
> > +	.probe = lis331dl_probe,
> > +	.remove = lis331dl_remove,
> > +	.id_table = lis331dl_id,
> > +};
> > +
> > +static int __init sensor_lis331dl_init(void)
> > +{
> > +	int res;
> > +
> > +	res = i2c_add_driver(&lis331dl_driver);
> > +	return res;
> > +}
> > +
> > +static void  __exit sensor_lis331dl_exit(void)
> > +{
> > +	i2c_del_driver(&lis331dl_driver);
> > +}
> > +
> > +module_init(sensor_lis331dl_init);
> > +module_exit(sensor_lis331dl_exit);
> > +
> > +MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>, Alan Cox");
> > +MODULE_DESCRIPTION("STMicroelectronics LIS331DL Accelerometer Driver");
> > +MODULE_LICENSE("GPL v2");
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at  http://www.tux.org/lkml/
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/4] isl29020: ambient light sensor
       [not found]       ` <20100414224542.GX30807-ahpEBR4enfnCULTFXS99ULNAH6kLmebB@public.gmane.org>
@ 2010-04-14 22:35         ` Alan Cox
       [not found]           ` <20100414233554.3f020155-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
  0 siblings, 1 reply; 24+ messages in thread
From: Alan Cox @ 2010-04-14 22:35 UTC (permalink / raw)
  To: Daniel Mack
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, khali-PUYAD+kWke1g9hUCZPvPmw,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Jonathan Cameron

> Would it be possible to make the existing driver for the ISL29003
> support the ISL29020 as well?

I dug the manuals out for these to take a look - the answer is they are
quite different chips. 

Alan

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 3/4] liss331d1: accelerometer driver
       [not found]       ` <4BC63DC5.8040501-hGVxb2UgFK3z+pZb47iToQ@public.gmane.org>
  2010-04-14 22:34         ` Daniel Mack
@ 2010-04-14 22:37         ` Alan Cox
  1 sibling, 0 replies; 24+ messages in thread
From: Alan Cox @ 2010-04-14 22:37 UTC (permalink / raw)
  To: Éric Piel
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, khali-PUYAD+kWke1g9hUCZPvPmw,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

> I wouldn't want to be too picky, if this driver works fine with your
> hardware and it's tested, why not, but from looking at the spec of
> this chip (and at the code of this driver), it looks like it could be
> completely compatible with the lis3lv02d driver (with lis3lv02d_i2c).
> Same registers, including the WHO_AM_I register which returns 0x3B
> (which is a supported version).

I will take a look in detail. The IRQ bit is different and as you say
the retries can be added to it anyway.

> 
> Have you tried and there were some specific incompatibilities? 

I am picking this project up rather than being directly responsible for
its history - chances are nobody has.

Alan

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/4] isl29020: ambient light sensor
       [not found]   ` <20100414125147.23181.5817.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
@ 2010-04-14 22:45     ` Daniel Mack
       [not found]       ` <20100414224542.GX30807-ahpEBR4enfnCULTFXS99ULNAH6kLmebB@public.gmane.org>
  0 siblings, 1 reply; 24+ messages in thread
From: Daniel Mack @ 2010-04-14 22:45 UTC (permalink / raw)
  To: Alan Cox
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, khali-PUYAD+kWke1g9hUCZPvPmw,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Jonathan Cameron

On Wed, Apr 14, 2010 at 01:51:49PM +0100, Alan Cox wrote:
> The LS driver will read the latest Lux measurement based upon the
> light brightness and will report the LUX output through sysfs interface.
> 
> Signed-off-by: Kalhan Trisal <kalhan.trisal-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> Signed-off-by: Alan Cox <alan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
> ---
> 
>  drivers/hwmon/Kconfig    |    9 ++
>  drivers/hwmon/Makefile   |    1 
>  drivers/hwmon/isl29020.c |  243 ++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 253 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/hwmon/isl29020.c

Would it be possible to make the existing driver for the ISL29003
support the ISL29020 as well?

Also note that there is a ALS (ambient light sensor) framework pending.
So patches against the 29003 driver should apply to this tree:

  git://git.kernel.org/pub/scm/linux/kernel/git/jic23/als.git

I copied the maintainer to this mail. Jonathan, any plans when ALS will
be merged?

Thanks,
Daniel



> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index 74f672d..1fa2533 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -1095,6 +1095,15 @@ config SENSORS_HMC6352
>  	  This driver provides support for the Honeywell HMC6352 compass,
>  	  providing configuration and heading data via sysfs.
>  
> +config SENSORS_ISL29020
> +	tristate "Intersil ISL29020 ALS"
> +	depends on I2C
> +	help
> +	  If you say yes here you get support for the ALS Devices
> +	  Ambient Light Sensor monitoring chip.
> +	  Range values can be configured using sysfs.
> +	  Lux data is accessible via sysfs.
> +
>  if ACPI
>  
>  comment "ACPI drivers"
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> index ad2ed36..13d6832 100644
> --- a/drivers/hwmon/Makefile
> +++ b/drivers/hwmon/Makefile
> @@ -53,6 +53,7 @@ obj-$(CONFIG_SENSORS_HMC6352)	+= hmc6352.o
>  obj-$(CONFIG_SENSORS_I5K_AMB)	+= i5k_amb.o
>  obj-$(CONFIG_SENSORS_IBMAEM)	+= ibmaem.o
>  obj-$(CONFIG_SENSORS_IBMPEX)	+= ibmpex.o
> +obj-$(CONFIG_SENSORS_ISL29020)	+= isl29020.o
>  obj-$(CONFIG_SENSORS_IT87)	+= it87.o
>  obj-$(CONFIG_SENSORS_K8TEMP)	+= k8temp.o
>  obj-$(CONFIG_SENSORS_K10TEMP)	+= k10temp.o
> diff --git a/drivers/hwmon/isl29020.c b/drivers/hwmon/isl29020.c
> new file mode 100644
> index 0000000..458140d
> --- /dev/null
> +++ b/drivers/hwmon/isl29020.c
> @@ -0,0 +1,243 @@
> +/*
> + * isl29020.c - Intersil  ALS Driver
> + *
> + * Copyright (C) 2008 Intel Corp
> + *
> + *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + *
> + * 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.,
> + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/slab.h>
> +#include <linux/i2c.h>
> +#include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
> +#include <linux/hwmon-vid.h>
> +#include <linux/err.h>
> +#include <linux/delay.h>
> +#include <linux/mutex.h>
> +#include <linux/sysfs.h>
> +
> +
> +#define ALS_MIN_RANGE_VAL 0
> +#define ALS_MAX_RANGE_VAL 5
> +
> +struct als_data {
> +	struct device *hwmon_dev;
> +};
> +
> +static unsigned int i2c_write_current_data(struct i2c_client *client,
> +					unsigned int reg, unsigned int value)
> +{
> +	int ret_val;
> +
> +	ret_val = i2c_smbus_write_byte_data(client, reg, value);
> +	return ret_val;
> +}
> +
> +static ssize_t als_sensing_range_show(struct device *dev,
> +			struct device_attribute *attr,  char *buf)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	int  val;
> +
> +	val = i2c_smbus_read_byte_data(client, 0x00);
> +	return sprintf(buf, "%d000\n", 1 << (2 * (val & 3)));
> +
> +}
> +
> +static ssize_t als_lux_output_data_show(struct device *dev,
> +			struct device_attribute *attr, char *buf)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	unsigned int ret_val, val;
> +	unsigned long int lux, max_count;
> +	int tempv1, tempv2;
> +
> +	max_count = 65535;
> +	tempv1 = i2c_smbus_read_byte_data(client, 0x02); /* MSB data */
> +	tempv2 = i2c_smbus_read_byte_data(client, 0x01); /* LSB data */
> +	ret_val = tempv1;
> +	ret_val = (ret_val << 8 | tempv2);
> +	val = i2c_smbus_read_byte_data(client, 0x00);
> +	lux = ((((1 << (2 * (val & 3))))*1000) * ret_val) / max_count;
> +	return sprintf(buf, "%ld\n", lux);
> +}
> +
> +static ssize_t als_sensing_range_store(struct device *dev,
> +		struct device_attribute *attr, const  char *buf, size_t count)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	unsigned int ret_val, set_val = 0;
> +	unsigned long val;
> +
> +	if (strict_strtoul(buf, 10, &val))
> +		return -EINVAL;
> +	ret_val = i2c_smbus_read_byte_data(client, 0x00);
> +	ret_val = ret_val & 0xFC; /*reset the bit before setting them */
> +	if (val == 1)
> +		set_val = (ret_val | 0x00); /* setting the 1:0  bit */
> +	else if (val == 2)
> +		set_val = (ret_val | 0x01);
> +	else if (val == 3)
> +		set_val = (ret_val | 0x02);
> +	else if (val == 4)
> +		set_val = (ret_val | 0x03);
> +	else
> +		goto invarg;
> +	i2c_write_current_data(client, 0x00, set_val);
> +	return count;
> +invarg:
> +	return -EINVAL;
> +}
> +
> +static ssize_t als_power_status_show(struct device *dev,
> +			struct device_attribute *attr, char *buf)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	int ret_val;
> +
> +	ret_val = i2c_smbus_read_byte_data(client, 0x00);
> +	ret_val = ret_val & 0x80;
> +	if (ret_val == 0x80)
> +		ret_val = 1;
> +	return sprintf(buf, "%x", ret_val);
> +}
> +
> +static ssize_t als_power_status_store(struct device *dev,
> +		struct device_attribute *attr, const char *buf, size_t count)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	unsigned long val = 0;
> +	char curr_val;
> +
> +	if (strict_strtoul(buf, 10, &val))
> +		return -EINVAL;
> +
> +	curr_val = i2c_smbus_read_byte_data(client, 0x00);
> +	if (val == 1)
> +		curr_val = curr_val | 0x80;
> +	else if (val == 0)
> +		curr_val = curr_val & 0x7F;
> +	else
> +		return -EINVAL;
> +	i2c_write_current_data(client, 0x00, curr_val);
> +	return count;
> +}
> +
> +static DEVICE_ATTR(sensing_range, S_IRUGO | S_IWUSR,
> +	als_sensing_range_show, als_sensing_range_store);
> +static DEVICE_ATTR(lux_output, S_IRUGO, als_lux_output_data_show, NULL);
> +static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
> +	als_power_status_show, als_power_status_store);
> +
> +static struct attribute *mid_att_als[] = {
> +	&dev_attr_sensing_range.attr,
> +	&dev_attr_lux_output.attr,
> +	&dev_attr_power_state.attr,
> +	NULL
> +};
> +
> +static struct attribute_group m_als_gr = {
> +	.name = "isl29020",
> +	.attrs = mid_att_als
> +};
> +
> +static void als_set_default_config(struct i2c_client *client)
> +{
> +	i2c_write_current_data(client, 0x00, 0xc0);
> +}
> +
> +static int  isl29020_probe(struct i2c_client *client,
> +					const struct i2c_device_id *id)
> +{
> +	int res;
> +	struct als_data *data;
> +
> +	data = kzalloc(sizeof(struct als_data), GFP_KERNEL);
> +	if (data == NULL) {
> +		printk(KERN_WARNING " isl29020: out of memory");
> +		return -ENOMEM;
> +	}
> +	i2c_set_clientdata(client, data);
> +
> +	res = sysfs_create_group(&client->dev.kobj, &m_als_gr);
> +	if (res) {
> +		printk(KERN_WARNING "isl29020: device create file failed!!\n");
> +		goto als_error1;
> +	}
> +	data->hwmon_dev = hwmon_device_register(&client->dev);
> +	if (IS_ERR(data->hwmon_dev)) {
> +		res = PTR_ERR(data->hwmon_dev);
> +		data->hwmon_dev = NULL;
> +		sysfs_remove_group(&client->dev.kobj, &m_als_gr);
> +		printk(KERN_ERR "isl29020:unable to register hwmon device\n");
> +		goto als_error1;
> +	}
> +	dev_info(&client->dev, "%s isl29020: ALS chip found\n", client->name);
> +	als_set_default_config(client);
> +	return res;
> +
> +als_error1:
> +	i2c_set_clientdata(client, NULL);
> +	kfree(data);
> +	return res;
> +}
> +
> +static int isl29020_remove(struct i2c_client *client)
> +{
> +	struct als_data *data = i2c_get_clientdata(client);
> +
> +	hwmon_device_unregister(data->hwmon_dev);
> +	sysfs_remove_group(&client->dev.kobj, &m_als_gr);
> +	kfree(data);
> +	return 0;
> +}
> +
> +static struct i2c_device_id isl29020_id[] = {
> +	{ "i2c_als", 0 },
> +	{ }
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, isl29020_id);
> +
> +static struct i2c_driver isl29020_driver = {
> +	.driver = {
> +	.name = "isl29020",
> +	},
> +	.probe = isl29020_probe,
> +	.remove = isl29020_remove,
> +	.id_table = isl29020_id,
> +};
> +
> +static int __init sensor_isl29020_init(void)
> +{
> +	return i2c_add_driver(&isl29020_driver);
> +}
> +
> +static void  __exit sensor_isl29020_exit(void)
> +{
> +	i2c_del_driver(&isl29020_driver);
> +}
> +
> +module_init(sensor_isl29020_init);
> +module_exit(sensor_isl29020_exit);
> +
> +MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org");
> +MODULE_DESCRIPTION("Intersil isl29020 ALS Driver");
> +MODULE_LICENSE("GPL v2");
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 3/4] liss331d1: accelerometer driver
       [not found]           ` <20100414223429.GW30807-ahpEBR4enfnCULTFXS99ULNAH6kLmebB@public.gmane.org>
@ 2010-04-14 23:05             ` Neil Brown
  2010-04-15  9:47               ` Éric Piel
  0 siblings, 1 reply; 24+ messages in thread
From: Neil Brown @ 2010-04-14 23:05 UTC (permalink / raw)
  To: Daniel Mack
  Cc: Éric Piel, Alan Cox, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	khali-PUYAD+kWke1g9hUCZPvPmw, linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On Thu, 15 Apr 2010 00:34:29 +0200
Daniel Mack <daniel-rDUAYElUppE@public.gmane.org> wrote:

> On Thu, Apr 15, 2010 at 12:12:21AM +0200, Éric Piel wrote:
> > Op 14-04-10 14:52, Alan Cox schreef:
> > > From: Kalhan Trisal <kalhan.trisal-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> > > 
> > > The acceleremeter driver reads the x,y,z coordinate registers and provides
> > > the information to user through the input layer
> > > 
> > > Conversion to input device, clean up and porting of retry fixes needed
> > > for AAVA done by Alan Cox.
> > Hello,
> > 
> > I wouldn't want to be too picky, if this driver works fine with your
> > hardware and it's tested, why not, but from looking at the spec of this
> > chip (and at the code of this driver), it looks like it could be
> > completely compatible with the lis3lv02d driver (with lis3lv02d_i2c).
> > Same registers, including the WHO_AM_I register which returns 0x3B
> > (which is a supported version).
> > 
> > Have you tried and there were some specific incompatibilities? To me, it
> > looks like the only thing not in the lis3lv02d is the read with multiple
> > retries, and it could be easily added if necessary for your hardware.
> 
> Yes, that would be better. Also because there's also a SPI version of
> the lis331dl. If support for this chip would be incorporated in the
> existing driver, they would automatically be supported as well.
> 

The Openmoko Freerunner has as lis302D which is an SPI version of a very
similar device, so making the one driver work on that was well would be nice
if possible.

The lis302d can detect threshold crossings and taps as well as simple
orientation and I found it useful to include support for those in the driver
as well.
In particular:
 1/ I allowed the 'data_rate' that was programmed to be any number (including 
    fractions and 0) and the driver would report at that rate, using a timer
    for rates below 50Hz.
    When the app is only interested in long-term change, this can
    significantly reduce the amount of data that has to be handled by
    userspace.

 2/ I allowed a 'threshold' to be set so that changes bigger than that get
    notified promptly even if that is faster than the requested data rate

 3/ I allowed taps to be detected and reported as BTN_X BTN_Y and BTN_Z
    input events.

Would it be sensible to include that support in this driver?  The
LIS331DL seem to have the same threshold and tap support.

NeilBrown



> Daniel
> 
> 
> > > Signed-off-by: Kalhan Trisal <kalhan.trisal-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> > > Signed-off-by: Alan Cox <alan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
> > > ---
> > > 
> > >  drivers/hwmon/Kconfig    |    8 +
> > >  drivers/hwmon/Makefile   |    1 
> > >  drivers/hwmon/lis331dl.c |  286 ++++++++++++++++++++++++++++++++++++++++++++++
> > >  3 files changed, 295 insertions(+), 0 deletions(-)
> > >  create mode 100644 drivers/hwmon/lis331dl.c
> > > 
> > > 
> > > diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> > > index 1fa2533..6868b9d 100644
> > > --- a/drivers/hwmon/Kconfig
> > > +++ b/drivers/hwmon/Kconfig
> > > @@ -1104,6 +1104,14 @@ config SENSORS_ISL29020
> > >  	  Range values can be configured using sysfs.
> > >  	  Lux data is accessible via sysfs.
> > >  
> > > +config SENSORS_LIS331DL
> > > +	tristate "STMicroeletronics LIS331DL three-axis digital accelerometer"
> > > +	depends on I2C
> > > +	help
> > > +	  If you say yes here you get support for the Accelerometer  Devices
> > > +	  Device can be configured using sysfs.
> > > +	  x y Z data can be   accessible via sysfs.
> > > +
> > >  if ACPI
> > >  
> > >  comment "ACPI drivers"
> > > diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> > > index 13d6832..ebeb2a2 100644
> > > --- a/drivers/hwmon/Makefile
> > > +++ b/drivers/hwmon/Makefile
> > > @@ -60,6 +60,7 @@ obj-$(CONFIG_SENSORS_K10TEMP)	+= k10temp.o
> > >  obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o
> > >  obj-$(CONFIG_SENSORS_LIS3_SPI)	+= lis3lv02d.o lis3lv02d_spi.o
> > >  obj-$(CONFIG_SENSORS_LIS3_I2C)	+= lis3lv02d.o lis3lv02d_i2c.o
> > > +obj-$(CONFIG_SENSORS_LIS331DL)	+= lis331dl.o
> > >  obj-$(CONFIG_SENSORS_LM63)	+= lm63.o
> > >  obj-$(CONFIG_SENSORS_LM70)	+= lm70.o
> > >  obj-$(CONFIG_SENSORS_LM73)	+= lm73.o
> > > diff --git a/drivers/hwmon/lis331dl.c b/drivers/hwmon/lis331dl.c
> > > new file mode 100644
> > > index 0000000..34009eb
> > > --- /dev/null
> > > +++ b/drivers/hwmon/lis331dl.c
> > > @@ -0,0 +1,286 @@
> > > +/*
> > > + * lis331dl.c - ST LIS331DL  Accelerometer Driver
> > > + *
> > > + * Copyright (C) 2009 Intel Corp
> > > + *
> > > + *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > > + *
> > > + * 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.,
> > > + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
> > > + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > > + *
> > > + */
> > > +
> > > +#include <linux/module.h>
> > > +#include <linux/init.h>
> > > +#include <linux/slab.h>
> > > +#include <linux/i2c.h>
> > > +#include <linux/err.h>
> > > +#include <linux/delay.h>
> > > +#include <linux/mutex.h>
> > > +#include <linux/sysfs.h>
> > > +#include <linux/input-polldev.h>
> > > +
> > > +
> > > +#define POLL_INTERVAL	50
> > > +
> > > +struct lis331dl {
> > > +	struct input_polled_dev *idev;
> > > +	struct i2c_client *client;
> > > +	struct mutex update_lock;
> > > +};
> > > +
> > > +static ssize_t data_rate_show(struct device *dev,
> > > +			struct device_attribute *attr, char *buf)
> > > +{
> > > +	struct i2c_client *client = to_i2c_client(dev);
> > > +	int val;
> > > +	int speed = 100;
> > > +
> > > +	val = i2c_smbus_read_byte_data(client, 0x20);
> > > +	if (val & 0x80); /* 1= 400HZ 0= 100HZ */
> > > +		speed = 400;
> > > +	return sprintf(buf, "%d\n", speed);
> > > +}
> > > +
> > > +static ssize_t power_mode_show(struct device *dev,
> > > +			struct device_attribute *attr, char *buf)
> > > +{
> > > +	struct i2c_client *client = to_i2c_client(dev);
> > > +	int val;
> > > +
> > > +	val = i2c_smbus_read_byte_data(client, 0x20) & 0x40;
> > > +	if (val == 0x40)
> > > +		val = 1;
> > > +	return sprintf(buf, "%d\n", val);
> > > +}
> > > +
> > > +static int read_with_retries(struct i2c_client *client, int r)
> > > +{
> > > +	int retries;
> > > +	int ret;
> > > +	
> > > +	for (retries = 0; retries < 5; retries++) {
> > > +		ret = i2c_smbus_read_byte_data(client, r);
> > > +		if (ret != -ETIMEDOUT)
> > > +			break;
> > > +		msleep(10);
> > > +	}
> > > +	return ret;
> > > +}
> > > +
> > > +static void lis331dl_poll(struct input_polled_dev *idev)
> > > +{
> > > +	struct input_dev *input = idev->input;
> > > +	struct lis331dl *data = idev->private;
> > > +	int x, y, z;
> > > +	struct i2c_client *client = data->client;
> > > +
> > > +	x = read_with_retries(client, 0x29);
> > > +	y = read_with_retries(client, 0x2B);
> > > +	z = read_with_retries(client, 0x2D);
> > > +
> > > +	input_report_abs(input, ABS_X, x);
> > > +	input_report_abs(input, ABS_Y, y);
> > > +	input_report_abs(input, ABS_Z, z);
> > > +	input_sync(input);
> > > +}
> > > +
> > > +static ssize_t data_rate_store(struct device *dev,
> > > +		struct device_attribute *attr, const char *buf, size_t count)
> > > +{
> > > +	struct i2c_client *client = to_i2c_client(dev);
> > > +	struct lis331dl *data = i2c_get_clientdata(client);
> > > +	unsigned int ret_val;
> > > +	unsigned long val;
> > > +
> > > +	if (strict_strtoul(buf, 10, &val))
> > > +		return -EINVAL;
> > > +
> > > +	mutex_lock(&data->update_lock);
> > > +
> > > +	ret_val = i2c_smbus_read_byte_data(client, 0x20);
> > > +	ret_val &= 0x7F;
> > > +
> > > +	switch (val) {
> > > +	case 400:
> > > +		ret_val |= 0x80;
> > > +	case 100:
> > > +		i2c_smbus_write_byte_data(client, 0x20, ret_val);
> > > +		break;
> > > +	default:		
> > > +		mutex_unlock(&data->update_lock);
> > > +		return -EINVAL;
> > > +	}
> > > +	mutex_unlock(&data->update_lock);
> > > +	return count;
> > > +}
> > > +
> > > +static ssize_t power_mode_store(struct device *dev,
> > > +		struct device_attribute *attr, const  char *buf, size_t count)
> > > +{
> > > +	struct i2c_client *client = to_i2c_client(dev);
> > > +	struct lis331dl *data = i2c_get_clientdata(client);
> > > +	unsigned int ret_val;
> > > +	unsigned long val;
> > > +
> > > +	if (strict_strtoul(buf, 10, &val))
> > > +		return -EINVAL;
> > > +
> > > +	mutex_lock(&data->update_lock);
> > > +
> > > +	ret_val = i2c_smbus_read_byte_data(client, 0x20);
> > > +	ret_val &= 0xBF;
> > > +	
> > > +	switch(val) {
> > > +	case 1:
> > > +		ret_val |= 0x40;
> > > +	case 0:
> > > +		i2c_smbus_write_byte_data(client, 0x20, ret_val);
> > > +		break;
> > > +	default:
> > > +		mutex_unlock(&data->update_lock);
> > > +		return -EINVAL;
> > > +	}
> > > +	mutex_unlock(&data->update_lock);
> > > +	return count;
> > > +}
> > > +
> > > +static DEVICE_ATTR(data_rate, S_IRUGO | S_IWUSR,
> > > +	data_rate_show, data_rate_store);
> > > +static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
> > > +	power_mode_show, power_mode_store);
> > > +
> > > +static struct attribute *mid_att_accelero[] = {
> > > +	&dev_attr_data_rate.attr,
> > > +	&dev_attr_power_state.attr,
> > > +	NULL
> > > +};
> > > +
> > > +static struct attribute_group m_accelero_gr = {
> > > +	.name = "lis331dl",
> > > +	.attrs = mid_att_accelero
> > > +};
> > > +
> > > +static void accel_set_default_config(struct i2c_client *client)
> > > +{
> > > +	i2c_smbus_write_byte_data(client, 0x20, 0x47);
> > > +}
> > > +
> > > +static int  lis331dl_probe(struct i2c_client *client,
> > > +					const struct i2c_device_id *id)
> > > +{
> > > +	int res;
> > > +	struct lis331dl *data;
> > > +	struct input_polled_dev *idev;
> > > +	struct input_dev *input;
> > > +
> > > +	data = kzalloc(sizeof(struct lis331dl), GFP_KERNEL);
> > > +	if (data == NULL) {
> > > +		dev_err(&client->dev, "lis331dl: out of memory\n");
> > > +		return -ENOMEM;
> > > +	}
> > > +	mutex_init(&data->update_lock);
> > > +	i2c_set_clientdata(client, data);
> > > +	data->client = client;
> > > +
> > > +	res = sysfs_create_group(&client->dev.kobj, &m_accelero_gr);
> > > +	if (res) {
> > > +		dev_err(&client->dev, "lis331dl: sysfs  group failed\n");
> > > +		goto accelero_error1;
> > > +	}
> > > +	idev = input_allocate_polled_device();
> > > +	if (!idev) {
> > > +		res = -ENOMEM;
> > > +		dev_err(&client->dev,
> > > +			"lis331dl: unable to register input device\n");
> > > +		goto accelero_error2;
> > > +	}
> > > +	idev->poll = lis331dl_poll;
> > > +	idev->poll_interval = POLL_INTERVAL;
> > > +
> > > +	idev->private = data;
> > > +	data->idev =  idev;
> > > +
> > > +	input = idev->input;
> > > +	input->name = "lis331dl";
> > > +	input->phys = "lis331dl/input0";
> > > +	input->id.bustype = BUS_I2C;
> > > +	input->dev.parent = &client->dev;
> > > +	input->evbit[0] = BIT_MASK(EV_ABS);
> > > +	input_set_abs_params(input, ABS_X, 0, 255, 2, 2);
> > > +	input_set_abs_params(input, ABS_Y, 0, 255, 2, 2);
> > > +	input_set_abs_params(input, ABS_Z, 0, 255, 2, 2);
> > > +
> > > +	res = input_register_polled_device(idev);
> > > +	if (res == 0) {
> > > +		dev_info(&client->dev,
> > > +			"%s lis331dl:  Accelerometer chip found",
> > > +							client->name);
> > > +		return 0;
> > > +	}
> > > +	input_free_polled_device(idev);
> > > +accelero_error2:
> > > +	sysfs_remove_group(&client->dev.kobj, &m_accelero_gr);
> > > +accelero_error1:
> > > +	i2c_set_clientdata(client, NULL);
> > > +	kfree(data);
> > > +	return res;
> > > +}
> > > +
> > > +static int lis331dl_remove(struct i2c_client *client)
> > > +{
> > > +	struct lis331dl *data = i2c_get_clientdata(client);
> > > +
> > > +	input_unregister_polled_device(data->idev);
> > > +	input_free_polled_device(data->idev);
> > > +	sysfs_remove_group(&client->dev.kobj, &m_accelero_gr);
> > > +	kfree(data);
> > > +	return 0;
> > > +}
> > > +
> > > +static struct i2c_device_id lis331dl_id[] = {
> > > +	{ "i2c_accel", 0 },
> > > +	{ }
> > > +};
> > > +
> > > +MODULE_DEVICE_TABLE(i2c, lis331dl_id);
> > > +
> > > +static struct i2c_driver lis331dl_driver = {
> > > +	.driver = {
> > > +	.name = "lis331dl",
> > > +	},
> > > +	.probe = lis331dl_probe,
> > > +	.remove = lis331dl_remove,
> > > +	.id_table = lis331dl_id,
> > > +};
> > > +
> > > +static int __init sensor_lis331dl_init(void)
> > > +{
> > > +	int res;
> > > +
> > > +	res = i2c_add_driver(&lis331dl_driver);
> > > +	return res;
> > > +}
> > > +
> > > +static void  __exit sensor_lis331dl_exit(void)
> > > +{
> > > +	i2c_del_driver(&lis331dl_driver);
> > > +}
> > > +
> > > +module_init(sensor_lis331dl_init);
> > > +module_exit(sensor_lis331dl_exit);
> > > +
> > > +MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>, Alan Cox");
> > > +MODULE_DESCRIPTION("STMicroelectronics LIS331DL Accelerometer Driver");
> > > +MODULE_LICENSE("GPL v2");
> > > 
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > > the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> > > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > > Please read the FAQ at  http://www.tux.org/lkml/
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at  http://www.tux.org/lkml/
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/4] isl29020: ambient light sensor
       [not found]           ` <20100414233554.3f020155-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
@ 2010-04-15  6:20             ` Daniel Mack
  2010-04-15 10:15               ` Jonathan Cameron
  0 siblings, 1 reply; 24+ messages in thread
From: Daniel Mack @ 2010-04-15  6:20 UTC (permalink / raw)
  To: Alan Cox
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, khali-PUYAD+kWke1g9hUCZPvPmw,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Jonathan Cameron

On Wed, Apr 14, 2010 at 11:35:54PM +0100, Alan Cox wrote:
> > Would it be possible to make the existing driver for the ISL29003
> > support the ISL29020 as well?
> 
> I dug the manuals out for these to take a look - the answer is they are
> quite different chips. 

Hmm, sad :(

However, the driver should be applied to the ALS tree after all, unless
Jonathan plans to drop the whole thing, which I doubt.

Thanks,
Daniel

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 3/4] liss331d1: accelerometer driver
  2010-04-14 23:05             ` Neil Brown
@ 2010-04-15  9:47               ` Éric Piel
  0 siblings, 0 replies; 24+ messages in thread
From: Éric Piel @ 2010-04-15  9:47 UTC (permalink / raw)
  To: Neil Brown
  Cc: Daniel Mack, Alan Cox, linux-i2c, khali, linux-input,
	linux-kernel, Samu Onkalo

On 15/04/10 01:05, Neil Brown wrote:
:
> 
> The Openmoko Freerunner has as lis302D which is an SPI version of a very
> similar device, so making the one driver work on that was well would be nice
> if possible.
Definitely!

> 
> The lis302d can detect threshold crossings and taps as well as simple
> orientation and I found it useful to include support for those in the driver
> as well.
> In particular:
>  1/ I allowed the 'data_rate' that was programmed to be any number (including 
>     fractions and 0) and the driver would report at that rate, using a timer
>     for rates below 50Hz.
>     When the app is only interested in long-term change, this can
>     significantly reduce the amount of data that has to be handled by
>     userspace.
Samu (from Nokia) has started to had such idea via the patch
lis3-setup-poll-interval-limits.patch which in now in the -mm tree. It
allows to specify the polling rate via the input interface
(/sys/devices/platform/lis3lv02d/input/input8/poll). But for now I don't
think the actual refresh rate is updated automatically, it would be a
nice addition.


> 
>  2/ I allowed a 'threshold' to be set so that changes bigger than that get
>     notified promptly even if that is faster than the requested data rate
It could be interesting too... but what interface are you using for the
userspace to specify this threshold? A sysfs file?

> 
>  3/ I allowed taps to be detected and reported as BTN_X BTN_Y and BTN_Z
>     input events.
This one should now be working with Samu's patch
lis3-interrupt-handlers-for-8bit-wakeup-and-click-events.patch also in
the -mm tree.

> 
> Would it be sensible to include that support in this driver?  The
> LIS331DL seem to have the same threshold and tap support.
So all in all, if you could have a look at what changes are necessary to
get the lis3lv02d driver work with your hardware, it would be great. (I
suspect it should be quite little.)

See you,
Eric

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 3/4] liss331d1: accelerometer driver
       [not found]         ` <4BC6EA64.4070308-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org>
@ 2010-04-15 10:02           ` Alan Cox
  0 siblings, 0 replies; 24+ messages in thread
From: Alan Cox @ 2010-04-15 10:02 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Éric Piel, linux-i2c-u79uwXL29TY76Z2rM5mHXA,
	khali-PUYAD+kWke1g9hUCZPvPmw, linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

> Err. Anyone get a feeling of deja vu here?
> 
> http://lists.lm-sensors.org/pipermail/lm-sensors/2009-September/026706.html
> 
> When Kalhan originally posted this driver it was pointed out that it
> was compatible with the existing one.  A complete lack of
> communications lead to Kalhan (and someone else, might have been Eric
> or Samu, can't recall) both implementing i2c support in the driver.
> Can't find it right now but I'm fairly sure Kahlan reported that
> worked fine for this chip as well?
> 
> So looks like a lack of communications here and that Alan has picked
> up an unnecessary driver.

Thanks it does indeed - except for the retry logic which has come from
another platform source and can be submitted in turn. Only other thing I
see odd is that the existing driver prints a scary error message when
there is no IRQ rather than just an info message.

Alan

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/4] isl29020: ambient light sensor
  2010-04-15  6:20             ` Daniel Mack
@ 2010-04-15 10:15               ` Jonathan Cameron
  0 siblings, 0 replies; 24+ messages in thread
From: Jonathan Cameron @ 2010-04-15 10:15 UTC (permalink / raw)
  To: Daniel Mack; +Cc: Alan Cox, linux-i2c, khali, linux-input, linux-kernel

On 04/15/10 07:20, Daniel Mack wrote:
> On Wed, Apr 14, 2010 at 11:35:54PM +0100, Alan Cox wrote:
>>> Would it be possible to make the existing driver for the ISL29003
>>> support the ISL29020 as well?
>>
>> I dug the manuals out for these to take a look - the answer is they are
>> quite different chips. 
> 
> Hmm, sad :(
> 
> However, the driver should be applied to the ALS tree after all, unless
> Jonathan plans to drop the whole thing, which I doubt.
Sadly ALS is dead.  Linus made it pretty clear he wasn't going to pull it.

Hence currently either ALS drivers are going into misc (and can be moved
elsewhere later), or we are taking them into IIO (and hence staging)
where they fit fine and we can sort out a bridge to input to answer Linus'
issue with the original patch set.

In the thread following Alan's repost (having moved this driver to misc)
Greg just pointed out the sysfs interface needed documenting, and I've
suggested that we sort out the naming properly (in a way compliant with
hwmon and the new IIO abi.  90% of what the ALS subsystem contributed was
defining the ABI anyway!

Jonathan

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 3/4] liss331d1: accelerometer driver
  2010-04-14 22:12     ` Éric Piel
       [not found]       ` <4BC63DC5.8040501-hGVxb2UgFK3z+pZb47iToQ@public.gmane.org>
@ 2010-04-15 10:28       ` Jonathan Cameron
       [not found]         ` <4BC6EA64.4070308-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org>
  1 sibling, 1 reply; 24+ messages in thread
From: Jonathan Cameron @ 2010-04-15 10:28 UTC (permalink / raw)
  To: Éric Piel; +Cc: Alan Cox, linux-i2c, khali, linux-input, linux-kernel

On 04/14/10 23:12, Éric Piel wrote:
> Op 14-04-10 14:52, Alan Cox schreef:
>> From: Kalhan Trisal <kalhan.trisal@intel.com>
>>
>> The acceleremeter driver reads the x,y,z coordinate registers and provides
>> the information to user through the input layer
>>
>> Conversion to input device, clean up and porting of retry fixes needed
>> for AAVA done by Alan Cox.
> Hello,
> 
> I wouldn't want to be too picky, if this driver works fine with your
> hardware and it's tested, why not, but from looking at the spec of this
> chip (and at the code of this driver), it looks like it could be
> completely compatible with the lis3lv02d driver (with lis3lv02d_i2c).
> Same registers, including the WHO_AM_I register which returns 0x3B
> (which is a supported version).
> 
> Have you tried and there were some specific incompatibilities? To me, it
> looks like the only thing not in the lis3lv02d is the read with multiple
> retries, and it could be easily added if necessary for your hardware.
> 
> Cheers,
> Eric
Err. Anyone get a feeling of deja vu here?

http://lists.lm-sensors.org/pipermail/lm-sensors/2009-September/026706.html

When Kalhan originally posted this driver it was pointed out that it was compatible
with the existing one.  A complete lack of communications lead to Kalhan (and someone
else, might have been Eric or Samu, can't recall) both implementing i2c support
in the driver. Can't find it right now but I'm fairly sure Kahlan reported that worked
fine for this chip as well?

So looks like a lack of communications here and that Alan has picked up an unnecessary
driver.

Jonathan
> 
>>
>> Signed-off-by: Kalhan Trisal <kalhan.trisal@intel.com>
>> Signed-off-by: Alan Cox <alan@linux.intel.com>
>> ---
>>
>>  drivers/hwmon/Kconfig    |    8 +
>>  drivers/hwmon/Makefile   |    1 
>>  drivers/hwmon/lis331dl.c |  286 ++++++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 295 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/hwmon/lis331dl.c
>>
>>
>> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
>> index 1fa2533..6868b9d 100644
>> --- a/drivers/hwmon/Kconfig
>> +++ b/drivers/hwmon/Kconfig
>> @@ -1104,6 +1104,14 @@ config SENSORS_ISL29020
>>  	  Range values can be configured using sysfs.
>>  	  Lux data is accessible via sysfs.
>>  
>> +config SENSORS_LIS331DL
>> +	tristate "STMicroeletronics LIS331DL three-axis digital accelerometer"
>> +	depends on I2C
>> +	help
>> +	  If you say yes here you get support for the Accelerometer  Devices
>> +	  Device can be configured using sysfs.
>> +	  x y Z data can be   accessible via sysfs.
>> +
>>  if ACPI
>>  
>>  comment "ACPI drivers"
>> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
>> index 13d6832..ebeb2a2 100644
>> --- a/drivers/hwmon/Makefile
>> +++ b/drivers/hwmon/Makefile
>> @@ -60,6 +60,7 @@ obj-$(CONFIG_SENSORS_K10TEMP)	+= k10temp.o
>>  obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o
>>  obj-$(CONFIG_SENSORS_LIS3_SPI)	+= lis3lv02d.o lis3lv02d_spi.o
>>  obj-$(CONFIG_SENSORS_LIS3_I2C)	+= lis3lv02d.o lis3lv02d_i2c.o
>> +obj-$(CONFIG_SENSORS_LIS331DL)	+= lis331dl.o
>>  obj-$(CONFIG_SENSORS_LM63)	+= lm63.o
>>  obj-$(CONFIG_SENSORS_LM70)	+= lm70.o
>>  obj-$(CONFIG_SENSORS_LM73)	+= lm73.o
>> diff --git a/drivers/hwmon/lis331dl.c b/drivers/hwmon/lis331dl.c
>> new file mode 100644
>> index 0000000..34009eb
>> --- /dev/null
>> +++ b/drivers/hwmon/lis331dl.c
>> @@ -0,0 +1,286 @@
>> +/*
>> + * lis331dl.c - ST LIS331DL  Accelerometer Driver
>> + *
>> + * Copyright (C) 2009 Intel Corp
>> + *
>> + *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> + *
>> + * 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.,
>> + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
>> + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> + *
>> + */
>> +
>> +#include <linux/module.h>
>> +#include <linux/init.h>
>> +#include <linux/slab.h>
>> +#include <linux/i2c.h>
>> +#include <linux/err.h>
>> +#include <linux/delay.h>
>> +#include <linux/mutex.h>
>> +#include <linux/sysfs.h>
>> +#include <linux/input-polldev.h>
>> +
>> +
>> +#define POLL_INTERVAL	50
>> +
>> +struct lis331dl {
>> +	struct input_polled_dev *idev;
>> +	struct i2c_client *client;
>> +	struct mutex update_lock;
>> +};
>> +
>> +static ssize_t data_rate_show(struct device *dev,
>> +			struct device_attribute *attr, char *buf)
>> +{
>> +	struct i2c_client *client = to_i2c_client(dev);
>> +	int val;
>> +	int speed = 100;
>> +
>> +	val = i2c_smbus_read_byte_data(client, 0x20);
>> +	if (val & 0x80); /* 1= 400HZ 0= 100HZ */
>> +		speed = 400;
>> +	return sprintf(buf, "%d\n", speed);
>> +}
>> +
>> +static ssize_t power_mode_show(struct device *dev,
>> +			struct device_attribute *attr, char *buf)
>> +{
>> +	struct i2c_client *client = to_i2c_client(dev);
>> +	int val;
>> +
>> +	val = i2c_smbus_read_byte_data(client, 0x20) & 0x40;
>> +	if (val == 0x40)
>> +		val = 1;
>> +	return sprintf(buf, "%d\n", val);
>> +}
>> +
>> +static int read_with_retries(struct i2c_client *client, int r)
>> +{
>> +	int retries;
>> +	int ret;
>> +	
>> +	for (retries = 0; retries < 5; retries++) {
>> +		ret = i2c_smbus_read_byte_data(client, r);
>> +		if (ret != -ETIMEDOUT)
>> +			break;
>> +		msleep(10);
>> +	}
>> +	return ret;
>> +}
>> +
>> +static void lis331dl_poll(struct input_polled_dev *idev)
>> +{
>> +	struct input_dev *input = idev->input;
>> +	struct lis331dl *data = idev->private;
>> +	int x, y, z;
>> +	struct i2c_client *client = data->client;
>> +
>> +	x = read_with_retries(client, 0x29);
>> +	y = read_with_retries(client, 0x2B);
>> +	z = read_with_retries(client, 0x2D);
>> +
>> +	input_report_abs(input, ABS_X, x);
>> +	input_report_abs(input, ABS_Y, y);
>> +	input_report_abs(input, ABS_Z, z);
>> +	input_sync(input);
>> +}
>> +
>> +static ssize_t data_rate_store(struct device *dev,
>> +		struct device_attribute *attr, const char *buf, size_t count)
>> +{
>> +	struct i2c_client *client = to_i2c_client(dev);
>> +	struct lis331dl *data = i2c_get_clientdata(client);
>> +	unsigned int ret_val;
>> +	unsigned long val;
>> +
>> +	if (strict_strtoul(buf, 10, &val))
>> +		return -EINVAL;
>> +
>> +	mutex_lock(&data->update_lock);
>> +
>> +	ret_val = i2c_smbus_read_byte_data(client, 0x20);
>> +	ret_val &= 0x7F;
>> +
>> +	switch (val) {
>> +	case 400:
>> +		ret_val |= 0x80;
>> +	case 100:
>> +		i2c_smbus_write_byte_data(client, 0x20, ret_val);
>> +		break;
>> +	default:		
>> +		mutex_unlock(&data->update_lock);
>> +		return -EINVAL;
>> +	}
>> +	mutex_unlock(&data->update_lock);
>> +	return count;
>> +}
>> +
>> +static ssize_t power_mode_store(struct device *dev,
>> +		struct device_attribute *attr, const  char *buf, size_t count)
>> +{
>> +	struct i2c_client *client = to_i2c_client(dev);
>> +	struct lis331dl *data = i2c_get_clientdata(client);
>> +	unsigned int ret_val;
>> +	unsigned long val;
>> +
>> +	if (strict_strtoul(buf, 10, &val))
>> +		return -EINVAL;
>> +
>> +	mutex_lock(&data->update_lock);
>> +
>> +	ret_val = i2c_smbus_read_byte_data(client, 0x20);
>> +	ret_val &= 0xBF;
>> +	
>> +	switch(val) {
>> +	case 1:
>> +		ret_val |= 0x40;
>> +	case 0:
>> +		i2c_smbus_write_byte_data(client, 0x20, ret_val);
>> +		break;
>> +	default:
>> +		mutex_unlock(&data->update_lock);
>> +		return -EINVAL;
>> +	}
>> +	mutex_unlock(&data->update_lock);
>> +	return count;
>> +}
>> +
>> +static DEVICE_ATTR(data_rate, S_IRUGO | S_IWUSR,
>> +	data_rate_show, data_rate_store);
>> +static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
>> +	power_mode_show, power_mode_store);
>> +
>> +static struct attribute *mid_att_accelero[] = {
>> +	&dev_attr_data_rate.attr,
>> +	&dev_attr_power_state.attr,
>> +	NULL
>> +};
>> +
>> +static struct attribute_group m_accelero_gr = {
>> +	.name = "lis331dl",
>> +	.attrs = mid_att_accelero
>> +};
>> +
>> +static void accel_set_default_config(struct i2c_client *client)
>> +{
>> +	i2c_smbus_write_byte_data(client, 0x20, 0x47);
>> +}
>> +
>> +static int  lis331dl_probe(struct i2c_client *client,
>> +					const struct i2c_device_id *id)
>> +{
>> +	int res;
>> +	struct lis331dl *data;
>> +	struct input_polled_dev *idev;
>> +	struct input_dev *input;
>> +
>> +	data = kzalloc(sizeof(struct lis331dl), GFP_KERNEL);
>> +	if (data == NULL) {
>> +		dev_err(&client->dev, "lis331dl: out of memory\n");
>> +		return -ENOMEM;
>> +	}
>> +	mutex_init(&data->update_lock);
>> +	i2c_set_clientdata(client, data);
>> +	data->client = client;
>> +
>> +	res = sysfs_create_group(&client->dev.kobj, &m_accelero_gr);
>> +	if (res) {
>> +		dev_err(&client->dev, "lis331dl: sysfs  group failed\n");
>> +		goto accelero_error1;
>> +	}
>> +	idev = input_allocate_polled_device();
>> +	if (!idev) {
>> +		res = -ENOMEM;
>> +		dev_err(&client->dev,
>> +			"lis331dl: unable to register input device\n");
>> +		goto accelero_error2;
>> +	}
>> +	idev->poll = lis331dl_poll;
>> +	idev->poll_interval = POLL_INTERVAL;
>> +
>> +	idev->private = data;
>> +	data->idev =  idev;
>> +
>> +	input = idev->input;
>> +	input->name = "lis331dl";
>> +	input->phys = "lis331dl/input0";
>> +	input->id.bustype = BUS_I2C;
>> +	input->dev.parent = &client->dev;
>> +	input->evbit[0] = BIT_MASK(EV_ABS);
>> +	input_set_abs_params(input, ABS_X, 0, 255, 2, 2);
>> +	input_set_abs_params(input, ABS_Y, 0, 255, 2, 2);
>> +	input_set_abs_params(input, ABS_Z, 0, 255, 2, 2);
>> +
>> +	res = input_register_polled_device(idev);
>> +	if (res == 0) {
>> +		dev_info(&client->dev,
>> +			"%s lis331dl:  Accelerometer chip found",
>> +							client->name);
>> +		return 0;
>> +	}
>> +	input_free_polled_device(idev);
>> +accelero_error2:
>> +	sysfs_remove_group(&client->dev.kobj, &m_accelero_gr);
>> +accelero_error1:
>> +	i2c_set_clientdata(client, NULL);
>> +	kfree(data);
>> +	return res;
>> +}
>> +
>> +static int lis331dl_remove(struct i2c_client *client)
>> +{
>> +	struct lis331dl *data = i2c_get_clientdata(client);
>> +
>> +	input_unregister_polled_device(data->idev);
>> +	input_free_polled_device(data->idev);
>> +	sysfs_remove_group(&client->dev.kobj, &m_accelero_gr);
>> +	kfree(data);
>> +	return 0;
>> +}
>> +
>> +static struct i2c_device_id lis331dl_id[] = {
>> +	{ "i2c_accel", 0 },
>> +	{ }
>> +};
>> +
>> +MODULE_DEVICE_TABLE(i2c, lis331dl_id);
>> +
>> +static struct i2c_driver lis331dl_driver = {
>> +	.driver = {
>> +	.name = "lis331dl",
>> +	},
>> +	.probe = lis331dl_probe,
>> +	.remove = lis331dl_remove,
>> +	.id_table = lis331dl_id,
>> +};
>> +
>> +static int __init sensor_lis331dl_init(void)
>> +{
>> +	int res;
>> +
>> +	res = i2c_add_driver(&lis331dl_driver);
>> +	return res;
>> +}
>> +
>> +static void  __exit sensor_lis331dl_exit(void)
>> +{
>> +	i2c_del_driver(&lis331dl_driver);
>> +}
>> +
>> +module_init(sensor_lis331dl_init);
>> +module_exit(sensor_lis331dl_exit);
>> +
>> +MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com>, Alan Cox");
>> +MODULE_DESCRIPTION("STMicroelectronics LIS331DL Accelerometer Driver");
>> +MODULE_LICENSE("GPL v2");
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at  http://www.tux.org/lkml/
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 3/4] liss331d1: accelerometer driver
       [not found]     ` <20100414125155.23181.56610.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
@ 2010-04-15 19:12       ` Pavel Machek
  0 siblings, 0 replies; 24+ messages in thread
From: Pavel Machek @ 2010-04-15 19:12 UTC (permalink / raw)
  To: Alan Cox
  Cc: linux-i2c-u79uwXL29TY76Z2rM5mHXA, khali-PUYAD+kWke1g9hUCZPvPmw,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On Wed 2010-04-14 13:52:00, Alan Cox wrote:
> From: Kalhan Trisal <kalhan.trisal-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> 
> The acceleremeter driver reads the x,y,z coordinate registers and provides
> the information to user through the input layer
> 
> Conversion to input device, clean up and porting of retry fixes needed
> for AAVA done by Alan Cox.

Out of interest, what is AAVA?
								Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2010-04-15 19:12 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-04-14 12:51 [PATCH 0/4] Various intel small device drivers Alan Cox
2010-04-14 12:51 ` [PATCH 1/4] hmc6352: Add driver for the HMC6352 compass Alan Cox
     [not found]   ` <20100414125136.23181.16788.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2010-04-14 13:48     ` Jonathan Cameron
     [not found]       ` <4BC5C7A8.1040807-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org>
2010-04-14 14:32         ` Alan Cox
     [not found]           ` <20100414153234.22765666-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org>
2010-04-14 14:51             ` Jonathan Cameron
2010-04-14 12:51 ` [PATCH 2/4] isl29020: ambient light sensor Alan Cox
     [not found]   ` <20100414125147.23181.5817.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2010-04-14 22:45     ` Daniel Mack
     [not found]       ` <20100414224542.GX30807-ahpEBR4enfnCULTFXS99ULNAH6kLmebB@public.gmane.org>
2010-04-14 22:35         ` Alan Cox
     [not found]           ` <20100414233554.3f020155-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2010-04-15  6:20             ` Daniel Mack
2010-04-15 10:15               ` Jonathan Cameron
2010-04-14 12:52 ` [PATCH 4/4] emc1403: thermal sensor support Alan Cox
     [not found] ` <20100414124913.23181.75903.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2010-04-14 12:52   ` [PATCH 3/4] liss331d1: accelerometer driver Alan Cox
2010-04-14 22:12     ` Éric Piel
     [not found]       ` <4BC63DC5.8040501-hGVxb2UgFK3z+pZb47iToQ@public.gmane.org>
2010-04-14 22:34         ` Daniel Mack
     [not found]           ` <20100414223429.GW30807-ahpEBR4enfnCULTFXS99ULNAH6kLmebB@public.gmane.org>
2010-04-14 23:05             ` Neil Brown
2010-04-15  9:47               ` Éric Piel
2010-04-14 22:37         ` Alan Cox
2010-04-15 10:28       ` Jonathan Cameron
     [not found]         ` <4BC6EA64.4070308-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org>
2010-04-15 10:02           ` Alan Cox
     [not found]     ` <20100414125155.23181.56610.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2010-04-15 19:12       ` Pavel Machek
2010-04-14 13:30   ` [PATCH 0/4] Various intel small device drivers Jean Delvare
     [not found]     ` <20100414153052.4e07f0cc-ig7AzVSIIG7kN2dkZ6Wm7A@public.gmane.org>
2010-04-14 13:49       ` Alan Cox
     [not found]         ` <20100414144912.12c83f51-qBU/x9rampVanCEyBjwyrvXRex20P6io@public.gmane.org>
2010-04-14 13:55           ` Jonathan Cameron
     [not found]             ` <4BC5C96B.7050901-KWPb1pKIrIJaa/9Udqfwiw@public.gmane.org>
2010-04-14 14:19               ` Alan Cox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).