aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mpu3050/compass
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/mpu3050/compass
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/misc/mpu3050/compass')
-rw-r--r--drivers/misc/mpu3050/compass/ak8975.c258
1 files changed, 258 insertions, 0 deletions
diff --git a/drivers/misc/mpu3050/compass/ak8975.c b/drivers/misc/mpu3050/compass/ak8975.c
new file mode 100644
index 00000000000..b8aed30ba39
--- /dev/null
+++ b/drivers/misc/mpu3050/compass/ak8975.c
@@ -0,0 +1,258 @@
1/*
2 $License:
3 Copyright (C) 2010 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 * @defgroup COMPASSDL (Motion Library - Accelerometer Driver Layer)
22 * @brief Provides the interface to setup and handle an accelerometers
23 * connected to the secondary I2C interface of the gyroscope.
24 *
25 * @{
26 * @file AK8975.c
27 * @brief Magnetometer setup and handling methods for AKM 8975 compass.
28 */
29
30/* ------------------ */
31/* - Include Files. - */
32/* ------------------ */
33
34#include <string.h>
35
36#ifdef __KERNEL__
37#include <linux/module.h>
38#endif
39
40#include "mpu.h"
41#include "mlsl.h"
42#include "mlos.h"
43
44#include <log.h>
45#undef MPL_LOG_TAG
46#define MPL_LOG_TAG "MPL-compass"
47
48
49#define AK8975_REG_ST1 (0x02)
50#define AK8975_REG_HXL (0x03)
51#define AK8975_REG_ST2 (0x09)
52
53#define AK8975_REG_CNTL (0x0A)
54
55#define AK8975_CNTL_MODE_POWER_DOWN (0x00)
56#define AK8975_CNTL_MODE_SINGLE_MEASUREMENT (0x01)
57
58int ak8975_suspend(void *mlsl_handle,
59 struct ext_slave_descr *slave,
60 struct ext_slave_platform_data *pdata)
61{
62 int result = ML_SUCCESS;
63 result =
64 MLSLSerialWriteSingle(mlsl_handle, pdata->address,
65 AK8975_REG_CNTL,
66 AK8975_CNTL_MODE_POWER_DOWN);
67 MLOSSleep(1); /* wait at least 100us */
68 ERROR_CHECK(result);
69 return result;
70}
71
72int ak8975_resume(void *mlsl_handle,
73 struct ext_slave_descr *slave,
74 struct ext_slave_platform_data *pdata)
75{
76 int result = ML_SUCCESS;
77 result =
78 MLSLSerialWriteSingle(mlsl_handle, pdata->address,
79 AK8975_REG_CNTL,
80 AK8975_CNTL_MODE_SINGLE_MEASUREMENT);
81 ERROR_CHECK(result);
82 return result;
83}
84
85int ak8975_read(void *mlsl_handle,
86 struct ext_slave_descr *slave,
87 struct ext_slave_platform_data *pdata, unsigned char *data)
88{
89 unsigned char regs[8];
90 unsigned char *stat = &regs[0];
91 unsigned char *stat2 = &regs[7];
92 int result = ML_SUCCESS;
93 int status = ML_SUCCESS;
94
95 result =
96 MLSLSerialRead(mlsl_handle, pdata->address, AK8975_REG_ST1,
97 8, regs);
98 ERROR_CHECK(result);
99
100 /*
101 * ST : data ready -
102 * Measurement has been completed and data is ready to be read.
103 */
104 if (*stat & 0x01) {
105 memcpy(data, &regs[1], 6);
106 status = ML_SUCCESS;
107 }
108
109 /*
110 * ST2 : data error -
111 * occurs when data read is started outside of a readable period;
112 * data read would not be correct.
113 * Valid in continuous measurement mode only.
114 * In single measurement mode this error should not occour but we
115 * stil account for it and return an error, since the data would be
116 * corrupted.
117 * DERR bit is self-clearing when ST2 register is read.
118 */
119 if (*stat2 & 0x04)
120 status = ML_ERROR_COMPASS_DATA_ERROR;
121 /*
122 * ST2 : overflow -
123 * the sum of the absolute values of all axis |X|+|Y|+|Z| < 2400uT.
124 * This is likely to happen in presence of an external magnetic
125 * disturbance; it indicates, the sensor data is incorrect and should
126 * be ignored.
127 * An error is returned.
128 * HOFL bit clears when a new measurement starts.
129 */
130 if (*stat2 & 0x08)
131 status = ML_ERROR_COMPASS_DATA_OVERFLOW;
132 /*
133 * ST : overrun -
134 * the previous sample was not fetched and lost.
135 * Valid in continuous measurement mode only.
136 * In single measurement mode this error should not occour and we
137 * don't consider this condition an error.
138 * DOR bit is self-clearing when ST2 or any meas. data register is
139 * read.
140 */
141 if (*stat & 0x02) {
142 /* status = ML_ERROR_COMPASS_DATA_UNDERFLOW; */
143 status = ML_SUCCESS;
144 }
145
146 /*
147 * trigger next measurement if:
148 * - stat is non zero;
149 * - if stat is zero and stat2 is non zero.
150 * Won't trigger if data is not ready and there was no error.
151 */
152 if (*stat != 0x00 || *stat2 != 0x00) {
153 result =
154 MLSLSerialWriteSingle(mlsl_handle, pdata->address,
155 AK8975_REG_CNTL,
156 AK8975_CNTL_MODE_SINGLE_MEASUREMENT);
157 ERROR_CHECK(result);
158 }
159
160 return status;
161}
162
163static int ak8975_config(void *mlsl_handle,
164 struct ext_slave_descr *slave,
165 struct ext_slave_platform_data *pdata,
166 struct ext_slave_config *data)
167{
168 int result;
169 if (!data->data)
170 return ML_ERROR_INVALID_PARAMETER;
171
172 switch (data->key) {
173 case MPU_SLAVE_WRITE_REGISTERS:
174 result = MLSLSerialWrite(mlsl_handle, pdata->address,
175 data->len,
176 (unsigned char *)data->data);
177 ERROR_CHECK(result);
178 break;
179 case MPU_SLAVE_CONFIG_ODR_SUSPEND:
180 case MPU_SLAVE_CONFIG_ODR_RESUME:
181 case MPU_SLAVE_CONFIG_FSR_SUSPEND:
182 case MPU_SLAVE_CONFIG_FSR_RESUME:
183 case MPU_SLAVE_CONFIG_MOT_THS:
184 case MPU_SLAVE_CONFIG_NMOT_THS:
185 case MPU_SLAVE_CONFIG_MOT_DUR:
186 case MPU_SLAVE_CONFIG_NMOT_DUR:
187 case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
188 case MPU_SLAVE_CONFIG_IRQ_RESUME:
189 default:
190 return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
191 };
192
193 return ML_SUCCESS;
194}
195
196static int ak8975_get_config(void *mlsl_handle,
197 struct ext_slave_descr *slave,
198 struct ext_slave_platform_data *pdata,
199 struct ext_slave_config *data)
200{
201 int result;
202 if (!data->data)
203 return ML_ERROR_INVALID_PARAMETER;
204
205 switch (data->key) {
206 case MPU_SLAVE_READ_REGISTERS:
207 {
208 unsigned char *serial_data = (unsigned char *)data->data;
209 result = MLSLSerialRead(mlsl_handle, pdata->address,
210 serial_data[0],
211 data->len - 1,
212 &serial_data[1]);
213 ERROR_CHECK(result);
214 break;
215 }
216 case MPU_SLAVE_CONFIG_ODR_SUSPEND:
217 case MPU_SLAVE_CONFIG_ODR_RESUME:
218 case MPU_SLAVE_CONFIG_FSR_SUSPEND:
219 case MPU_SLAVE_CONFIG_FSR_RESUME:
220 case MPU_SLAVE_CONFIG_MOT_THS:
221 case MPU_SLAVE_CONFIG_NMOT_THS:
222 case MPU_SLAVE_CONFIG_MOT_DUR:
223 case MPU_SLAVE_CONFIG_NMOT_DUR:
224 case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
225 case MPU_SLAVE_CONFIG_IRQ_RESUME:
226 default:
227 return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
228 };
229
230 return ML_SUCCESS;
231}
232
233struct ext_slave_descr ak8975_descr = {
234 /*.init = */ NULL,
235 /*.exit = */ NULL,
236 /*.suspend = */ ak8975_suspend,
237 /*.resume = */ ak8975_resume,
238 /*.read = */ ak8975_read,
239 /*.config = */ ak8975_config,
240 /*.get_config = */ ak8975_get_config,
241 /*.name = */ "ak8975",
242 /*.type = */ EXT_SLAVE_TYPE_COMPASS,
243 /*.id = */ COMPASS_ID_AKM,
244 /*.reg = */ 0x01,
245 /*.len = */ 9,
246 /*.endian = */ EXT_SLAVE_LITTLE_ENDIAN,
247 /*.range = */ {9830, 4000}
248};
249
250struct ext_slave_descr *ak8975_get_slave_descr(void)
251{
252 return &ak8975_descr;
253}
254EXPORT_SYMBOL(ak8975_get_slave_descr);
255
256/**
257 * @}
258 */