2 * hmc6352.c - Honeywell Compass Driver
4 * Copyright (C) 2009 Intel Corp
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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.
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.
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 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 #include <linux/module.h>
25 #include <linux/slab.h>
26 #include <linux/i2c.h>
27 #include <linux/err.h>
28 #include <linux/delay.h>
29 #include <linux/sysfs.h>
30 #include <linux/nospec.h>
32 static DEFINE_MUTEX(compass_mutex
);
34 static int compass_command(struct i2c_client
*c
, u8 cmd
)
36 int ret
= i2c_master_send(c
, &cmd
, 1);
38 dev_warn(&c
->dev
, "command '%c' failed.\n", cmd
);
42 static int compass_store(struct device
*dev
, const char *buf
, size_t count
,
45 struct i2c_client
*c
= to_i2c_client(dev
);
49 ret
= kstrtoul(buf
, 10, &val
);
52 if (val
>= strlen(map
))
54 val
= array_index_nospec(val
, strlen(map
));
55 mutex_lock(&compass_mutex
);
56 ret
= compass_command(c
, map
[val
]);
57 mutex_unlock(&compass_mutex
);
63 static ssize_t
compass_calibration_store(struct device
*dev
,
64 struct device_attribute
*attr
, const char *buf
, size_t count
)
66 return compass_store(dev
, buf
, count
, "EC");
69 static ssize_t
compass_power_mode_store(struct device
*dev
,
70 struct device_attribute
*attr
, const char *buf
, size_t count
)
72 return compass_store(dev
, buf
, count
, "SW");
75 static ssize_t
compass_heading_data_show(struct device
*dev
,
76 struct device_attribute
*attr
, char *buf
)
78 struct i2c_client
*client
= to_i2c_client(dev
);
79 unsigned char i2c_data
[2];
82 mutex_lock(&compass_mutex
);
83 ret
= compass_command(client
, 'A');
85 mutex_unlock(&compass_mutex
);
88 msleep(10); /* sending 'A' cmd we need to wait for 7-10 millisecs */
89 ret
= i2c_master_recv(client
, i2c_data
, 2);
90 mutex_unlock(&compass_mutex
);
92 dev_warn(dev
, "i2c read data cmd failed\n");
95 ret
= (i2c_data
[0] << 8) | i2c_data
[1];
96 return sprintf(buf
, "%d.%d\n", ret
/10, ret
%10);
100 static DEVICE_ATTR(heading0_input
, S_IRUGO
, compass_heading_data_show
, NULL
);
101 static DEVICE_ATTR(calibration
, S_IWUSR
, NULL
, compass_calibration_store
);
102 static DEVICE_ATTR(power_state
, S_IWUSR
, NULL
, compass_power_mode_store
);
104 static struct attribute
*mid_att_compass
[] = {
105 &dev_attr_heading0_input
.attr
,
106 &dev_attr_calibration
.attr
,
107 &dev_attr_power_state
.attr
,
111 static const struct attribute_group m_compass_gr
= {
113 .attrs
= mid_att_compass
116 static int hmc6352_probe(struct i2c_client
*client
,
117 const struct i2c_device_id
*id
)
121 res
= sysfs_create_group(&client
->dev
.kobj
, &m_compass_gr
);
123 dev_err(&client
->dev
, "device_create_file failed\n");
126 dev_info(&client
->dev
, "%s HMC6352 compass chip found\n",
131 static int hmc6352_remove(struct i2c_client
*client
)
133 sysfs_remove_group(&client
->dev
.kobj
, &m_compass_gr
);
137 static struct i2c_device_id hmc6352_id
[] = {
142 MODULE_DEVICE_TABLE(i2c
, hmc6352_id
);
144 static struct i2c_driver hmc6352_driver
= {
148 .probe
= hmc6352_probe
,
149 .remove
= hmc6352_remove
,
150 .id_table
= hmc6352_id
,
153 module_i2c_driver(hmc6352_driver
);
155 MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com");
156 MODULE_DESCRIPTION("hmc6352 Compass Driver");
157 MODULE_LICENSE("GPL v2");