aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKalhan Trisal <kalhan.trisal@intel.com>2010-08-09 20:21:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-09 23:45:10 -0400
commitcfa3b24c38b58cb6acabe6441b4668e530e957af (patch)
tree666af3dd6eb990d244ef19d16d099107da11b28d /drivers
parent5f1209a1a4cf24798408fa0893258dcbefcf6be9 (diff)
hmc6352: add driver for the HMC6352 compass
This driver will report the heading values in degrees to the sysfs interface. The values returned are headings . e.g. 245.6 Alan: Cleanups requested now all folded in and a sysfs description to keep Andrew happy. The sysfs description now resembles hwmon. Signed-off-by: Kalhan Trisal <kalhan.trisal@intel.com> Reviewed-by: Jean Delvare <khali@linux-fr.org> Signed-off-by: Alan Cox <alan@linux.intel.com> Cc: Jonathan Cameron <jic23@cam.ac.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/misc/Kconfig7
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/hmc6352.c166
3 files changed, 174 insertions, 0 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 3b4b7562b2fa..0b591b658243 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -314,6 +314,13 @@ config SENSORS_BH1780
314 This driver can also be built as a module. If so, the module 314 This driver can also be built as a module. If so, the module
315 will be called bh1780gli. 315 will be called bh1780gli.
316 316
317config HMC6352
318 tristate "Honeywell HMC6352 compass"
319 depends on I2C
320 help
321 This driver provides support for the Honeywell HMC6352 compass,
322 providing configuration and heading data via sysfs.
323
317config EP93XX_PWM 324config EP93XX_PWM
318 tristate "EP93xx PWM support" 325 tristate "EP93xx PWM support"
319 depends on ARCH_EP93XX 326 depends on ARCH_EP93XX
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index c0621fbacb27..255a80dc9d73 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_DS1682) += ds1682.o
30obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o 30obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o
31obj-$(CONFIG_C2PORT) += c2port/ 31obj-$(CONFIG_C2PORT) += c2port/
32obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/ 32obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/
33obj-$(CONFIG_HMC6352) += hmc6352.o
33obj-y += eeprom/ 34obj-y += eeprom/
34obj-y += cb710/ 35obj-y += cb710/
35obj-$(CONFIG_VMWARE_BALLOON) += vmware_balloon.o 36obj-$(CONFIG_VMWARE_BALLOON) += vmware_balloon.o
diff --git a/drivers/misc/hmc6352.c b/drivers/misc/hmc6352.c
new file mode 100644
index 000000000000..234bfcaf2099
--- /dev/null
+++ b/drivers/misc/hmc6352.c
@@ -0,0 +1,166 @@
1/*
2 * hmc6352.c - Honeywell Compass Driver
3 *
4 * Copyright (C) 2009 Intel Corp
5 *
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21 *
22 */
23
24#include <linux/module.h>
25#include <linux/init.h>
26#include <linux/slab.h>
27#include <linux/i2c.h>
28#include <linux/err.h>
29#include <linux/delay.h>
30#include <linux/sysfs.h>
31
32static DEFINE_MUTEX(compass_mutex);
33
34static int compass_command(struct i2c_client *c, u8 cmd)
35{
36 int ret = i2c_master_send(c, &cmd, 1);
37 if (ret < 0)
38 dev_warn(&c->dev, "command '%c' failed.\n", cmd);
39 return ret;
40}
41
42static int compass_store(struct device *dev, const char *buf, size_t count,
43 const char *map)
44{
45 struct i2c_client *c = to_i2c_client(dev);
46 int ret;
47 unsigned long val;
48
49 if (strict_strtoul(buf, 10, &val))
50 return -EINVAL;
51 if (val >= strlen(map))
52 return -EINVAL;
53 mutex_lock(&compass_mutex);
54 ret = compass_command(c, map[val]);
55 mutex_unlock(&compass_mutex);
56 if (ret < 0)
57 return ret;
58 return count;
59}
60
61static ssize_t compass_calibration_store(struct device *dev,
62 struct device_attribute *attr, const char *buf, size_t count)
63{
64 return compass_store(dev, buf, count, "EC");
65}
66
67static ssize_t compass_power_mode_store(struct device *dev,
68 struct device_attribute *attr, const char *buf, size_t count)
69{
70 return compass_store(dev, buf, count, "SW");
71}
72
73static ssize_t compass_heading_data_show(struct device *dev,
74 struct device_attribute *attr, char *buf)
75{
76 struct i2c_client *client = to_i2c_client(dev);
77 unsigned char i2c_data[2];
78 unsigned int ret;
79
80 mutex_lock(&compass_mutex);
81 ret = compass_command(client, 'A');
82 if (ret != 1) {
83 mutex_unlock(&compass_mutex);
84 return ret;
85 }
86 msleep(10); /* sending 'A' cmd we need to wait for 7-10 millisecs */
87 ret = i2c_master_recv(client, i2c_data, 2);
88 mutex_unlock(&compass_mutex);
89 if (ret != 1) {
90 dev_warn(dev, "i2c read data cmd failed\n");
91 return ret;
92 }
93 ret = (i2c_data[0] << 8) | i2c_data[1];
94 return sprintf(buf, "%d.%d\n", ret/10, ret%10);
95}
96
97
98static DEVICE_ATTR(heading0_input, S_IRUGO, compass_heading_data_show, NULL);
99static DEVICE_ATTR(calibration, S_IWUSR, NULL, compass_calibration_store);
100static DEVICE_ATTR(power_state, S_IWUSR, NULL, compass_power_mode_store);
101
102static struct attribute *mid_att_compass[] = {
103 &dev_attr_heading0_input.attr,
104 &dev_attr_calibration.attr,
105 &dev_attr_power_state.attr,
106 NULL
107};
108
109static const struct attribute_group m_compass_gr = {
110 .name = "hmc6352",
111 .attrs = mid_att_compass
112};
113
114static int hmc6352_probe(struct i2c_client *client,
115 const struct i2c_device_id *id)
116{
117 int res;
118
119 res = sysfs_create_group(&client->dev.kobj, &m_compass_gr);
120 if (res) {
121 dev_err(&client->dev, "device_create_file failed\n");
122 return res;
123 }
124 dev_info(&client->dev, "%s HMC6352 compass chip found\n",
125 client->name);
126 return 0;
127}
128
129static int hmc6352_remove(struct i2c_client *client)
130{
131 sysfs_remove_group(&client->dev.kobj, &m_compass_gr);
132 return 0;
133}
134
135static struct i2c_device_id hmc6352_id[] = {
136 { "hmc6352", 0 },
137 { }
138};
139
140MODULE_DEVICE_TABLE(i2c, hmc6352_id);
141
142static struct i2c_driver hmc6352_driver = {
143 .driver = {
144 .name = "hmc6352",
145 },
146 .probe = hmc6352_probe,
147 .remove = hmc6352_remove,
148 .id_table = hmc6352_id,
149};
150
151static int __init sensor_hmc6352_init(void)
152{
153 return i2c_add_driver(&hmc6352_driver);
154}
155
156static void __exit sensor_hmc6352_exit(void)
157{
158 i2c_del_driver(&hmc6352_driver);
159}
160
161module_init(sensor_hmc6352_init);
162module_exit(sensor_hmc6352_exit);
163
164MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com");
165MODULE_DESCRIPTION("hmc6352 Compass Driver");
166MODULE_LICENSE("GPL v2");