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/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>
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 if (strict_strtoul(buf
, 10, &val
))
51 if (val
>= strlen(map
))
53 mutex_lock(&compass_mutex
);
54 ret
= compass_command(c
, map
[val
]);
55 mutex_unlock(&compass_mutex
);
61 static ssize_t
compass_calibration_store(struct device
*dev
,
62 struct device_attribute
*attr
, const char *buf
, size_t count
)
64 return compass_store(dev
, buf
, count
, "EC");
67 static ssize_t
compass_power_mode_store(struct device
*dev
,
68 struct device_attribute
*attr
, const char *buf
, size_t count
)
70 return compass_store(dev
, buf
, count
, "SW");
73 static ssize_t
compass_heading_data_show(struct device
*dev
,
74 struct device_attribute
*attr
, char *buf
)
76 struct i2c_client
*client
= to_i2c_client(dev
);
77 unsigned char i2c_data
[2];
80 mutex_lock(&compass_mutex
);
81 ret
= compass_command(client
, 'A');
83 mutex_unlock(&compass_mutex
);
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
);
90 dev_warn(dev
, "i2c read data cmd failed\n");
93 ret
= (i2c_data
[0] << 8) | i2c_data
[1];
94 return sprintf(buf
, "%d.%d\n", ret
/10, ret
%10);
98 static DEVICE_ATTR(heading0_input
, S_IRUGO
, compass_heading_data_show
, NULL
);
99 static DEVICE_ATTR(calibration
, S_IWUSR
, NULL
, compass_calibration_store
);
100 static DEVICE_ATTR(power_state
, S_IWUSR
, NULL
, compass_power_mode_store
);
102 static struct attribute
*mid_att_compass
[] = {
103 &dev_attr_heading0_input
.attr
,
104 &dev_attr_calibration
.attr
,
105 &dev_attr_power_state
.attr
,
109 static const struct attribute_group m_compass_gr
= {
111 .attrs
= mid_att_compass
114 static int hmc6352_probe(struct i2c_client
*client
,
115 const struct i2c_device_id
*id
)
119 res
= sysfs_create_group(&client
->dev
.kobj
, &m_compass_gr
);
121 dev_err(&client
->dev
, "device_create_file failed\n");
124 dev_info(&client
->dev
, "%s HMC6352 compass chip found\n",
129 static int hmc6352_remove(struct i2c_client
*client
)
131 sysfs_remove_group(&client
->dev
.kobj
, &m_compass_gr
);
135 static struct i2c_device_id hmc6352_id
[] = {
140 MODULE_DEVICE_TABLE(i2c
, hmc6352_id
);
142 static struct i2c_driver hmc6352_driver
= {
146 .probe
= hmc6352_probe
,
147 .remove
= hmc6352_remove
,
148 .id_table
= hmc6352_id
,
151 static int __init
sensor_hmc6352_init(void)
153 return i2c_add_driver(&hmc6352_driver
);
156 static void __exit
sensor_hmc6352_exit(void)
158 i2c_del_driver(&hmc6352_driver
);
161 module_init(sensor_hmc6352_init
);
162 module_exit(sensor_hmc6352_exit
);
164 MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com");
165 MODULE_DESCRIPTION("hmc6352 Compass Driver");
166 MODULE_LICENSE("GPL v2");