aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/inv_mpu/compass/hscdtd002b.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/misc/inv_mpu/compass/hscdtd002b.c
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/misc/inv_mpu/compass/hscdtd002b.c')
-rw-r--r--drivers/misc/inv_mpu/compass/hscdtd002b.c294
1 files changed, 294 insertions, 0 deletions
diff --git a/drivers/misc/inv_mpu/compass/hscdtd002b.c b/drivers/misc/inv_mpu/compass/hscdtd002b.c
new file mode 100644
index 00000000000..4f6013cbe3d
--- /dev/null
+++ b/drivers/misc/inv_mpu/compass/hscdtd002b.c
@@ -0,0 +1,294 @@
1/*
2 $License:
3 Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 $
18 */
19
20/**
21 * @addtogroup COMPASSDL
22 *
23 * @{
24 * @file hscdtd002b.c
25 * @brief Magnetometer setup and handling methods for Alps HSCDTD002B
26 * compass.
27 */
28
29/* -------------------------------------------------------------------------- */
30
31#include <linux/i2c.h>
32#include <linux/module.h>
33#include <linux/moduleparam.h>
34#include <linux/kernel.h>
35#include <linux/errno.h>
36#include <linux/slab.h>
37#include <linux/delay.h>
38#include "mpu-dev.h"
39
40#include <log.h>
41#include <linux/mpu.h>
42#include "mlsl.h"
43#include "mldl_cfg.h"
44#undef MPL_LOG_TAG
45#define MPL_LOG_TAG "MPL-compass"
46
47/* -------------------------------------------------------------------------- */
48#define COMPASS_HSCDTD002B_STAT (0x18)
49#define COMPASS_HSCDTD002B_CTRL1 (0x1B)
50#define COMPASS_HSCDTD002B_CTRL2 (0x1C)
51#define COMPASS_HSCDTD002B_CTRL3 (0x1D)
52#define COMPASS_HSCDTD002B_DATAX (0x10)
53
54/* -------------------------------------------------------------------------- */
55static int hscdtd002b_suspend(void *mlsl_handle,
56 struct ext_slave_descr *slave,
57 struct ext_slave_platform_data *pdata)
58{
59 int result = INV_SUCCESS;
60
61 /* Power mode: stand-by */
62 result =
63 inv_serial_single_write(mlsl_handle, pdata->address,
64 COMPASS_HSCDTD002B_CTRL1, 0x00);
65 if (result) {
66 LOG_RESULT_LOCATION(result);
67 return result;
68 }
69 msleep(1); /* turn-off time */
70
71 return result;
72}
73
74static int hscdtd002b_resume(void *mlsl_handle,
75 struct ext_slave_descr *slave,
76 struct ext_slave_platform_data *pdata)
77{
78 int result = INV_SUCCESS;
79
80 /* Soft reset */
81 result =
82 inv_serial_single_write(mlsl_handle, pdata->address,
83 COMPASS_HSCDTD002B_CTRL3, 0x80);
84 if (result) {
85 LOG_RESULT_LOCATION(result);
86 return result;
87 }
88 /* Force state; Power mode: active */
89 result =
90 inv_serial_single_write(mlsl_handle, pdata->address,
91 COMPASS_HSCDTD002B_CTRL1, 0x82);
92 if (result) {
93 LOG_RESULT_LOCATION(result);
94 return result;
95 }
96 /* Data ready enable */
97 result =
98 inv_serial_single_write(mlsl_handle, pdata->address,
99 COMPASS_HSCDTD002B_CTRL2, 0x08);
100 if (result) {
101 LOG_RESULT_LOCATION(result);
102 return result;
103 }
104 msleep(1); /* turn-on time */
105
106 return result;
107}
108
109static int hscdtd002b_read(void *mlsl_handle,
110 struct ext_slave_descr *slave,
111 struct ext_slave_platform_data *pdata,
112 unsigned char *data)
113{
114 unsigned char stat;
115 int result = INV_SUCCESS;
116 int status = INV_SUCCESS;
117
118 /* Read status reg. to check if data is ready */
119 result =
120 inv_serial_read(mlsl_handle, pdata->address,
121 COMPASS_HSCDTD002B_STAT, 1, &stat);
122 if (result) {
123 LOG_RESULT_LOCATION(result);
124 return result;
125 }
126 if (stat & 0x40) {
127 result =
128 inv_serial_read(mlsl_handle, pdata->address,
129 COMPASS_HSCDTD002B_DATAX, 6,
130 (unsigned char *)data);
131 if (result) {
132 LOG_RESULT_LOCATION(result);
133 return result;
134 }
135 status = INV_SUCCESS;
136 } else if (stat & 0x20) {
137 status = INV_ERROR_COMPASS_DATA_OVERFLOW;
138 } else {
139 status = INV_ERROR_COMPASS_DATA_NOT_READY;
140 }
141 /* trigger next measurement read */
142 result =
143 inv_serial_single_write(mlsl_handle, pdata->address,
144 COMPASS_HSCDTD002B_CTRL3, 0x40);
145 if (result) {
146 LOG_RESULT_LOCATION(result);
147 return result;
148 }
149
150 return status;
151}
152
153static struct ext_slave_descr hscdtd002b_descr = {
154 .init = NULL,
155 .exit = NULL,
156 .suspend = hscdtd002b_suspend,
157 .resume = hscdtd002b_resume,
158 .read = hscdtd002b_read,
159 .config = NULL,
160 .get_config = NULL,
161 .name = "hscdtd002b",
162 .type = EXT_SLAVE_TYPE_COMPASS,
163 .id = COMPASS_ID_HSCDTD002B,
164 .read_reg = 0x10,
165 .read_len = 6,
166 .endian = EXT_SLAVE_LITTLE_ENDIAN,
167 .range = {9830, 4000},
168 .trigger = NULL,
169};
170
171static
172struct ext_slave_descr *hscdtd002b_get_slave_descr(void)
173{
174 return &hscdtd002b_descr;
175}
176
177/* -------------------------------------------------------------------------- */
178struct hscdtd002b_mod_private_data {
179 struct i2c_client *client;
180 struct ext_slave_platform_data *pdata;
181};
182
183static unsigned short normal_i2c[] = { I2C_CLIENT_END };
184
185static int hscdtd002b_mod_probe(struct i2c_client *client,
186 const struct i2c_device_id *devid)
187{
188 struct ext_slave_platform_data *pdata;
189 struct hscdtd002b_mod_private_data *private_data;
190 int result = 0;
191
192 dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
193
194 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
195 result = -ENODEV;
196 goto out_no_free;
197 }
198
199 pdata = client->dev.platform_data;
200 if (!pdata) {
201 dev_err(&client->adapter->dev,
202 "Missing platform data for slave %s\n", devid->name);
203 result = -EFAULT;
204 goto out_no_free;
205 }
206
207 private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
208 if (!private_data) {
209 result = -ENOMEM;
210 goto out_no_free;
211 }
212
213 i2c_set_clientdata(client, private_data);
214 private_data->client = client;
215 private_data->pdata = pdata;
216
217 result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
218 hscdtd002b_get_slave_descr);
219 if (result) {
220 dev_err(&client->adapter->dev,
221 "Slave registration failed: %s, %d\n",
222 devid->name, result);
223 goto out_free_memory;
224 }
225
226 return result;
227
228out_free_memory:
229 kfree(private_data);
230out_no_free:
231 dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
232 return result;
233
234}
235
236static int hscdtd002b_mod_remove(struct i2c_client *client)
237{
238 struct hscdtd002b_mod_private_data *private_data =
239 i2c_get_clientdata(client);
240
241 dev_dbg(&client->adapter->dev, "%s\n", __func__);
242
243 inv_mpu_unregister_slave(client, private_data->pdata,
244 hscdtd002b_get_slave_descr);
245
246 kfree(private_data);
247 return 0;
248}
249
250static const struct i2c_device_id hscdtd002b_mod_id[] = {
251 { "hscdtd002b", COMPASS_ID_HSCDTD002B },
252 {}
253};
254
255MODULE_DEVICE_TABLE(i2c, hscdtd002b_mod_id);
256
257static struct i2c_driver hscdtd002b_mod_driver = {
258 .class = I2C_CLASS_HWMON,
259 .probe = hscdtd002b_mod_probe,
260 .remove = hscdtd002b_mod_remove,
261 .id_table = hscdtd002b_mod_id,
262 .driver = {
263 .owner = THIS_MODULE,
264 .name = "hscdtd002b_mod",
265 },
266 .address_list = normal_i2c,
267};
268
269static int __init hscdtd002b_mod_init(void)
270{
271 int res = i2c_add_driver(&hscdtd002b_mod_driver);
272 pr_info("%s: Probe name %s\n", __func__, "hscdtd002b_mod");
273 if (res)
274 pr_err("%s failed\n", __func__);
275 return res;
276}
277
278static void __exit hscdtd002b_mod_exit(void)
279{
280 pr_info("%s\n", __func__);
281 i2c_del_driver(&hscdtd002b_mod_driver);
282}
283
284module_init(hscdtd002b_mod_init);
285module_exit(hscdtd002b_mod_exit);
286
287MODULE_AUTHOR("Invensense Corporation");
288MODULE_DESCRIPTION("Driver to integrate HSCDTD002B sensor with the MPU");
289MODULE_LICENSE("GPL");
290MODULE_ALIAS("hscdtd002b_mod");
291
292/**
293 * @}
294 */