import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / magnetometer / bmm050-new / bmm050.c
1 /* bmm050.c - bmm050 compass driver
2 *
3 *
4 * This software program is licensed subject to the GNU General Public License
5 * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html
6
7 * (C) Copyright 2011 Bosch Sensortec GmbH
8 * All Rights Reserved
9 */
10
11 #include <linux/interrupt.h>
12 #include <linux/i2c.h>
13 #include <linux/slab.h>
14 #include <linux/irq.h>
15 #include <linux/miscdevice.h>
16 #include <asm/uaccess.h>
17 #include <asm/atomic.h>
18 #include <linux/delay.h>
19 #include <linux/input.h>
20 #include <linux/workqueue.h>
21 #include <linux/kobject.h>
22 #include <linux/platform_device.h>
23 #include <linux/earlysuspend.h>
24 #include <linux/time.h>
25 #include <linux/hrtimer.h>
26
27
28
29 #include <mach/mt_typedefs.h>
30 #include <mach/mt_gpio.h>
31 #include <mach/mt_pm_ldo.h>
32
33
34 #define POWER_NONE_MACRO MT65XX_POWER_NONE
35
36 #include <cust_mag.h>
37 #include <linux/hwmsen_helper.h>
38 #include <linux/hwmsensor.h>
39 #include <linux/hwmsen_dev.h>
40 #include <linux/sensors_io.h>
41 #include "bmm050.h"
42 #include "mag.h"
43
44 /*----------------------------------------------------------------------------*/
45 /* BMM050 API Section */
46 /*----------------------------------------------------------------------------*/
47 #define BMC050_U16 unsigned short
48 #define BMC050_S16 signed short
49 #define BMC050_S32 signed int
50
51 #define BMC050_BUS_WR_RETURN_TYPE char
52
53 /*
54 //#define BMC050_BUS_WR_PARAM_TYPES\
55 // unsigned char, unsigned char, unsigned char *, unsigned char
56 //#define BMC050_BUS_WR_PARAM_ORDER\
57 // (device_addr, register_addr, register_data, wr_len)
58 */
59
60 #define BMC050_BUS_WRITE_FUNC(device_addr, register_addr, register_data, wr_len) bus_write(device_addr, register_addr, register_data, wr_len)
61
62 #define BMC050_BUS_RD_RETURN_TYPE char
63
64 /*
65 //#define BMC050_BUS_RD_PARAM_TYPES\
66 // unsigned char, unsigned char, unsigned char *, unsigned char
67
68 //#define BMC050_BUS_RD_PARAM_ORDER (device_addr, register_addr, register_data)
69 */
70
71 #define BMC050_BUS_READ_FUNC(device_addr, register_addr, register_data, rd_len) bus_read(device_addr, register_addr, register_data, rd_len)
72
73 #define BMC050_DELAY_RETURN_TYPE void
74
75 #define BMC050_DELAY_PARAM_TYPES unsigned int
76
77 /*
78 //#define BMC050_DELAY_FUNC(delay_in_msec)
79 //delay_func(delay_in_msec)
80 */
81
82 #define BMC050_DELAY_POWEROFF_SUSPEND 1
83 #define BMC050_DELAY_SUSPEND_SLEEP 2
84 #define BMC050_DELAY_SLEEP_ACTIVE 1
85 #define BMC050_DELAY_ACTIVE_SLEEP 1
86 #define BMC050_DELAY_SLEEP_SUSPEND 1
87 #define BMC050_DELAY_ACTIVE_SUSPEND 1
88 #define BMC050_DELAY_SLEEP_POWEROFF 1
89 #define BMC050_DELAY_ACTIVE_POWEROFF 1
90 #define BMC050_DELAY_SETTLING_TIME 2
91
92
93 #define BMC050_RETURN_FUNCTION_TYPE char
94 #define BMC050_I2C_ADDRESS 0x10
95
96 /*General Info datas*/
97 #define BMC050_SOFT_RESET7_ON 1
98 #define BMC050_SOFT_RESET1_ON 1
99 #define BMC050_SOFT_RESET7_OFF 0
100 #define BMC050_SOFT_RESET1_OFF 0
101 #define BMC050_DELAY_SOFTRESET 1
102
103 /* Fixed Data Registers */
104 #define BMC050_CHIP_ID 0x40
105 #define BMC050_REVISION_ID 0x41
106
107 /* Data Registers */
108 #define BMC050_DATAX_LSB 0x42
109 #define BMC050_DATAX_MSB 0x43
110 #define BMC050_DATAY_LSB 0x44
111 #define BMC050_DATAY_MSB 0x45
112 #define BMC050_DATAZ_LSB 0x46
113 #define BMC050_DATAZ_MSB 0x47
114 #define BMC050_R_LSB 0x48
115 #define BMC050_R_MSB 0x49
116
117 /* Status Registers */
118 #define BMC050_INT_STAT 0x4A
119
120 /* Control Registers */
121 #define BMC050_POWER_CNTL 0x4B
122 #define BMC050_CONTROL 0x4C
123 #define BMC050_INT_CNTL 0x4D
124 #define BMC050_SENS_CNTL 0x4E
125 #define BMC050_LOW_THRES 0x4F
126 #define BMC050_HIGH_THRES 0x50
127 #define BMC050_NO_REPETITIONS_XY 0x51
128 #define BMC050_NO_REPETITIONS_Z 0x52
129
130 /* Trim Extended Registers */
131 #define BMC050_DIG_X1 0x5D
132 #define BMC050_DIG_Y1 0x5E
133 #define BMC050_DIG_Z4_LSB 0x62
134 #define BMC050_DIG_Z4_MSB 0x63
135 #define BMC050_DIG_X2 0x64
136 #define BMC050_DIG_Y2 0x65
137 #define BMC050_DIG_Z2_LSB 0x68
138 #define BMC050_DIG_Z2_MSB 0x69
139 #define BMC050_DIG_Z1_LSB 0x6A
140 #define BMC050_DIG_Z1_MSB 0x6B
141 #define BMC050_DIG_XYZ1_LSB 0x6C
142 #define BMC050_DIG_XYZ1_MSB 0x6D
143 #define BMC050_DIG_Z3_LSB 0x6E
144 #define BMC050_DIG_Z3_MSB 0x6F
145 #define BMC050_DIG_XY2 0x70
146 #define BMC050_DIG_XY1 0x71
147
148
149 /* Data X LSB Regsiter */
150 #define BMC050_DATAX_LSB_VALUEX__POS 3
151 #define BMC050_DATAX_LSB_VALUEX__LEN 5
152 #define BMC050_DATAX_LSB_VALUEX__MSK 0xF8
153 #define BMC050_DATAX_LSB_VALUEX__REG BMC050_DATAX_LSB
154
155 #define BMC050_DATAX_LSB_TESTX__POS 0
156 #define BMC050_DATAX_LSB_TESTX__LEN 1
157 #define BMC050_DATAX_LSB_TESTX__MSK 0x01
158 #define BMC050_DATAX_LSB_TESTX__REG BMC050_DATAX_LSB
159
160 /* Data Y LSB Regsiter */
161 #define BMC050_DATAY_LSB_VALUEY__POS 3
162 #define BMC050_DATAY_LSB_VALUEY__LEN 5
163 #define BMC050_DATAY_LSB_VALUEY__MSK 0xF8
164 #define BMC050_DATAY_LSB_VALUEY__REG BMC050_DATAY_LSB
165
166 #define BMC050_DATAY_LSB_TESTY__POS 0
167 #define BMC050_DATAY_LSB_TESTY__LEN 1
168 #define BMC050_DATAY_LSB_TESTY__MSK 0x01
169 #define BMC050_DATAY_LSB_TESTY__REG BMC050_DATAY_LSB
170
171 /* Data Z LSB Regsiter */
172 #define BMC050_DATAZ_LSB_VALUEZ__POS 1
173 #define BMC050_DATAZ_LSB_VALUEZ__LEN 7
174 #define BMC050_DATAZ_LSB_VALUEZ__MSK 0xFE
175 #define BMC050_DATAZ_LSB_VALUEZ__REG BMC050_DATAZ_LSB
176
177 #define BMC050_DATAZ_LSB_TESTZ__POS 0
178 #define BMC050_DATAZ_LSB_TESTZ__LEN 1
179 #define BMC050_DATAZ_LSB_TESTZ__MSK 0x01
180 #define BMC050_DATAZ_LSB_TESTZ__REG BMC050_DATAZ_LSB
181
182 /* Hall Resistance LSB Regsiter */
183 #define BMC050_R_LSB_VALUE__POS 2
184 #define BMC050_R_LSB_VALUE__LEN 6
185 #define BMC050_R_LSB_VALUE__MSK 0xFC
186 #define BMC050_R_LSB_VALUE__REG BMC050_R_LSB
187
188 #define BMC050_DATA_RDYSTAT__POS 0
189 #define BMC050_DATA_RDYSTAT__LEN 1
190 #define BMC050_DATA_RDYSTAT__MSK 0x01
191 #define BMC050_DATA_RDYSTAT__REG BMC050_R_LSB
192
193 /* Interupt Status Register */
194 #define BMC050_INT_STAT_DOR__POS 7
195 #define BMC050_INT_STAT_DOR__LEN 1
196 #define BMC050_INT_STAT_DOR__MSK 0x80
197 #define BMC050_INT_STAT_DOR__REG BMC050_INT_STAT
198
199 #define BMC050_INT_STAT_OVRFLOW__POS 6
200 #define BMC050_INT_STAT_OVRFLOW__LEN 1
201 #define BMC050_INT_STAT_OVRFLOW__MSK 0x40
202 #define BMC050_INT_STAT_OVRFLOW__REG BMC050_INT_STAT
203
204 #define BMC050_INT_STAT_HIGH_THZ__POS 5
205 #define BMC050_INT_STAT_HIGH_THZ__LEN 1
206 #define BMC050_INT_STAT_HIGH_THZ__MSK 0x20
207 #define BMC050_INT_STAT_HIGH_THZ__REG BMC050_INT_STAT
208
209 #define BMC050_INT_STAT_HIGH_THY__POS 4
210 #define BMC050_INT_STAT_HIGH_THY__LEN 1
211 #define BMC050_INT_STAT_HIGH_THY__MSK 0x10
212 #define BMC050_INT_STAT_HIGH_THY__REG BMC050_INT_STAT
213
214 #define BMC050_INT_STAT_HIGH_THX__POS 3
215 #define BMC050_INT_STAT_HIGH_THX__LEN 1
216 #define BMC050_INT_STAT_HIGH_THX__MSK 0x08
217 #define BMC050_INT_STAT_HIGH_THX__REG BMC050_INT_STAT
218
219 #define BMC050_INT_STAT_LOW_THZ__POS 2
220 #define BMC050_INT_STAT_LOW_THZ__LEN 1
221 #define BMC050_INT_STAT_LOW_THZ__MSK 0x04
222 #define BMC050_INT_STAT_LOW_THZ__REG BMC050_INT_STAT
223
224 #define BMC050_INT_STAT_LOW_THY__POS 1
225 #define BMC050_INT_STAT_LOW_THY__LEN 1
226 #define BMC050_INT_STAT_LOW_THY__MSK 0x02
227 #define BMC050_INT_STAT_LOW_THY__REG BMC050_INT_STAT
228
229 #define BMC050_INT_STAT_LOW_THX__POS 0
230 #define BMC050_INT_STAT_LOW_THX__LEN 1
231 #define BMC050_INT_STAT_LOW_THX__MSK 0x01
232 #define BMC050_INT_STAT_LOW_THX__REG BMC050_INT_STAT
233
234 /* Power Control Register */
235 #define BMC050_POWER_CNTL_SRST7__POS 7
236 #define BMC050_POWER_CNTL_SRST7__LEN 1
237 #define BMC050_POWER_CNTL_SRST7__MSK 0x80
238 #define BMC050_POWER_CNTL_SRST7__REG BMC050_POWER_CNTL
239
240 #define BMC050_POWER_CNTL_SPI3_EN__POS 2
241 #define BMC050_POWER_CNTL_SPI3_EN__LEN 1
242 #define BMC050_POWER_CNTL_SPI3_EN__MSK 0x04
243 #define BMC050_POWER_CNTL_SPI3_EN__REG BMC050_POWER_CNTL
244
245 #define BMC050_POWER_CNTL_SRST1__POS 1
246 #define BMC050_POWER_CNTL_SRST1__LEN 1
247 #define BMC050_POWER_CNTL_SRST1__MSK 0x02
248 #define BMC050_POWER_CNTL_SRST1__REG BMC050_POWER_CNTL
249
250 #define BMC050_POWER_CNTL_PCB__POS 0
251 #define BMC050_POWER_CNTL_PCB__LEN 1
252 #define BMC050_POWER_CNTL_PCB__MSK 0x01
253 #define BMC050_POWER_CNTL_PCB__REG BMC050_POWER_CNTL
254
255 /* Control Register */
256 #define BMC050_CNTL_ADV_ST__POS 6
257 #define BMC050_CNTL_ADV_ST__LEN 2
258 #define BMC050_CNTL_ADV_ST__MSK 0xC0
259 #define BMC050_CNTL_ADV_ST__REG BMC050_CONTROL
260
261 #define BMC050_CNTL_DR__POS 3
262 #define BMC050_CNTL_DR__LEN 3
263 #define BMC050_CNTL_DR__MSK 0x38
264 #define BMC050_CNTL_DR__REG BMC050_CONTROL
265
266 #define BMC050_CNTL_OPMODE__POS 1
267 #define BMC050_CNTL_OPMODE__LEN 2
268 #define BMC050_CNTL_OPMODE__MSK 0x06
269 #define BMC050_CNTL_OPMODE__REG BMC050_CONTROL
270
271 #define BMC050_CNTL_S_TEST__POS 0
272 #define BMC050_CNTL_S_TEST__LEN 1
273 #define BMC050_CNTL_S_TEST__MSK 0x01
274 #define BMC050_CNTL_S_TEST__REG BMC050_CONTROL
275
276 /* Interupt Control Register */
277 #define BMC050_INT_CNTL_DOR_EN__POS 7
278 #define BMC050_INT_CNTL_DOR_EN__LEN 1
279 #define BMC050_INT_CNTL_DOR_EN__MSK 0x80
280 #define BMC050_INT_CNTL_DOR_EN__REG BMC050_INT_CNTL
281
282 #define BMC050_INT_CNTL_OVRFLOW_EN__POS 6
283 #define BMC050_INT_CNTL_OVRFLOW_EN__LEN 1
284 #define BMC050_INT_CNTL_OVRFLOW_EN__MSK 0x40
285 #define BMC050_INT_CNTL_OVRFLOW_EN__REG BMC050_INT_CNTL
286
287 #define BMC050_INT_CNTL_HIGH_THZ_EN__POS 5
288 #define BMC050_INT_CNTL_HIGH_THZ_EN__LEN 1
289 #define BMC050_INT_CNTL_HIGH_THZ_EN__MSK 0x20
290 #define BMC050_INT_CNTL_HIGH_THZ_EN__REG BMC050_INT_CNTL
291
292 #define BMC050_INT_CNTL_HIGH_THY_EN__POS 4
293 #define BMC050_INT_CNTL_HIGH_THY_EN__LEN 1
294 #define BMC050_INT_CNTL_HIGH_THY_EN__MSK 0x10
295 #define BMC050_INT_CNTL_HIGH_THY_EN__REG BMC050_INT_CNTL
296
297 #define BMC050_INT_CNTL_HIGH_THX_EN__POS 3
298 #define BMC050_INT_CNTL_HIGH_THX_EN__LEN 1
299 #define BMC050_INT_CNTL_HIGH_THX_EN__MSK 0x08
300 #define BMC050_INT_CNTL_HIGH_THX_EN__REG BMC050_INT_CNTL
301
302 #define BMC050_INT_CNTL_LOW_THZ_EN__POS 2
303 #define BMC050_INT_CNTL_LOW_THZ_EN__LEN 1
304 #define BMC050_INT_CNTL_LOW_THZ_EN__MSK 0x04
305 #define BMC050_INT_CNTL_LOW_THZ_EN__REG BMC050_INT_CNTL
306
307 #define BMC050_INT_CNTL_LOW_THY_EN__POS 1
308 #define BMC050_INT_CNTL_LOW_THY_EN__LEN 1
309 #define BMC050_INT_CNTL_LOW_THY_EN__MSK 0x02
310 #define BMC050_INT_CNTL_LOW_THY_EN__REG BMC050_INT_CNTL
311
312 #define BMC050_INT_CNTL_LOW_THX_EN__POS 0
313 #define BMC050_INT_CNTL_LOW_THX_EN__LEN 1
314 #define BMC050_INT_CNTL_LOW_THX_EN__MSK 0x01
315 #define BMC050_INT_CNTL_LOW_THX_EN__REG BMC050_INT_CNTL
316
317 /* Sensor Control Register */
318 #define BMC050_SENS_CNTL_DRDY_EN__POS 7
319 #define BMC050_SENS_CNTL_DRDY_EN__LEN 1
320 #define BMC050_SENS_CNTL_DRDY_EN__MSK 0x80
321 #define BMC050_SENS_CNTL_DRDY_EN__REG BMC050_SENS_CNTL
322
323 #define BMC050_SENS_CNTL_IE__POS 6
324 #define BMC050_SENS_CNTL_IE__LEN 1
325 #define BMC050_SENS_CNTL_IE__MSK 0x40
326 #define BMC050_SENS_CNTL_IE__REG BMC050_SENS_CNTL
327
328 #define BMC050_SENS_CNTL_CHANNELZ__POS 5
329 #define BMC050_SENS_CNTL_CHANNELZ__LEN 1
330 #define BMC050_SENS_CNTL_CHANNELZ__MSK 0x20
331 #define BMC050_SENS_CNTL_CHANNELZ__REG BMC050_SENS_CNTL
332
333 #define BMC050_SENS_CNTL_CHANNELY__POS 4
334 #define BMC050_SENS_CNTL_CHANNELY__LEN 1
335 #define BMC050_SENS_CNTL_CHANNELY__MSK 0x10
336 #define BMC050_SENS_CNTL_CHANNELY__REG BMC050_SENS_CNTL
337
338 #define BMC050_SENS_CNTL_CHANNELX__POS 3
339 #define BMC050_SENS_CNTL_CHANNELX__LEN 1
340 #define BMC050_SENS_CNTL_CHANNELX__MSK 0x08
341 #define BMC050_SENS_CNTL_CHANNELX__REG BMC050_SENS_CNTL
342
343 #define BMC050_SENS_CNTL_DR_POLARITY__POS 2
344 #define BMC050_SENS_CNTL_DR_POLARITY__LEN 1
345 #define BMC050_SENS_CNTL_DR_POLARITY__MSK 0x04
346 #define BMC050_SENS_CNTL_DR_POLARITY__REG BMC050_SENS_CNTL
347
348 #define BMC050_SENS_CNTL_INTERRUPT_LATCH__POS 1
349 #define BMC050_SENS_CNTL_INTERRUPT_LATCH__LEN 1
350 #define BMC050_SENS_CNTL_INTERRUPT_LATCH__MSK 0x02
351 #define BMC050_SENS_CNTL_INTERRUPT_LATCH__REG BMC050_SENS_CNTL
352
353 #define BMC050_SENS_CNTL_INTERRUPT_POLARITY__POS 0
354 #define BMC050_SENS_CNTL_INTERRUPT_POLARITY__LEN 1
355 #define BMC050_SENS_CNTL_INTERRUPT_POLARITY__MSK 0x01
356 #define BMC050_SENS_CNTL_INTERRUPT_POLARITY__REG BMC050_SENS_CNTL
357
358 /* Register 6D */
359 #define BMC050_DIG_XYZ1_MSB__POS 0
360 #define BMC050_DIG_XYZ1_MSB__LEN 7
361 #define BMC050_DIG_XYZ1_MSB__MSK 0x7F
362 #define BMC050_DIG_XYZ1_MSB__REG BMC050_DIG_XYZ1_MSB
363
364
365 #define BMC050_X_AXIS 0
366 #define BMC050_Y_AXIS 1
367 #define BMC050_Z_AXIS 2
368 #define BMC050_RESISTANCE 3
369 #define BMC050_X 1
370 #define BMC050_Y 2
371 #define BMC050_Z 4
372 #define BMC050_XYZ 7
373
374 /* Constants */
375 #define BMC050_NULL 0
376 #define BMC050_INTPIN_DISABLE 1
377 #define BMC050_INTPIN_ENABLE 0
378 #define BMC050_DISABLE 0
379 #define BMC050_ENABLE 1
380 #define BMC050_CHANNEL_DISABLE 1
381 #define BMC050_CHANNEL_ENABLE 0
382 #define BMC050_INTPIN_LATCH_ENABLE 1
383 #define BMC050_INTPIN_LATCH_DISABLE 0
384 #define BMC050_OFF 0
385 #define BMC050_ON 1
386
387 #define BMC050_NORMAL_MODE 0x00
388 #define BMC050_FORCED_MODE 0x01
389 #define BMC050_SUSPEND_MODE 0x02
390 #define BMC050_SLEEP_MODE 0x03
391
392 #define BMC050_ADVANCED_SELFTEST_OFF 0
393 #define BMC050_ADVANCED_SELFTEST_NEGATIVE 2
394 #define BMC050_ADVANCED_SELFTEST_POSITIVE 3
395
396 #define BMC050_NEGATIVE_SATURATION_Z -32767
397 #define BMC050_POSITIVE_SATURATION_Z 32767
398
399 #define BMC050_SPI_RD_MASK 0x80
400 #define BMC050_READ_SET 0x01
401
402 #define E_BMC050_NULL_PTR ((char)-127)
403 #define E_BMC050_COMM_RES ((char)-1)
404 #define E_BMC050_OUT_OF_RANGE ((char)-2)
405 #define E_BMC050_UNDEFINED_MODE 0
406
407 #define BMC050_WR_FUNC_PTR\
408 char (*bus_write)(unsigned char, unsigned char,\
409 unsigned char *, unsigned char)
410
411 #define BMC050_RD_FUNC_PTR\
412 char (*bus_read)(unsigned char, unsigned char,\
413 unsigned char *, unsigned char)
414 #define BMC050_MDELAY_DATA_TYPE unsigned int
415
416 /*Shifting Constants*/
417 #define SHIFT_RIGHT_1_POSITION 1
418 #define SHIFT_RIGHT_2_POSITION 2
419 #define SHIFT_RIGHT_3_POSITION 3
420 #define SHIFT_RIGHT_4_POSITION 4
421 #define SHIFT_RIGHT_5_POSITION 5
422 #define SHIFT_RIGHT_6_POSITION 6
423 #define SHIFT_RIGHT_7_POSITION 7
424 #define SHIFT_RIGHT_8_POSITION 8
425
426 #define SHIFT_LEFT_1_POSITION 1
427 #define SHIFT_LEFT_2_POSITION 2
428 #define SHIFT_LEFT_3_POSITION 3
429 #define SHIFT_LEFT_4_POSITION 4
430 #define SHIFT_LEFT_5_POSITION 5
431 #define SHIFT_LEFT_6_POSITION 6
432 #define SHIFT_LEFT_7_POSITION 7
433 #define SHIFT_LEFT_8_POSITION 8
434
435 /* Conversion factors*/
436 #define BMC050_CONVFACTOR_LSB_UT 6
437
438 /* get bit slice */
439 #define BMC050_GET_BITSLICE(regvar, bitname)\
440 ((regvar & bitname##__MSK) >> bitname##__POS)
441
442 /* Set bit slice */
443 #define BMC050_SET_BITSLICE(regvar, bitname, val)\
444 ((regvar & ~bitname##__MSK) | ((val<<bitname##__POS)&bitname##__MSK))
445
446 /* compensated output value returned if sensor had overflow */
447 #define BMC050_OVERFLOW_OUTPUT -32768
448 /* Flipcore overflow ADC value */
449 #define BMC050_FLIP_OVERFLOW_ADCVAL -4096
450 /* Hall overflow 1 ADC value */
451 #define BMC050_HALL_OVERFLOW_ADCVAL -16384
452
453
454 #define BMC050_PRESETMODE_LOWPOWER 1
455 #define BMC050_PRESETMODE_REGULAR 2
456 #define BMC050_PRESETMODE_HIGHACCURACY 3
457
458 /* PRESET MODES - DATA RATES */
459 #define BMC050_LOWPOWER_DR BMC050_DR_10HZ
460 #define BMC050_REGULAR_DR BMC050_DR_10HZ
461 #define BMC050_HIGHACCURACY_DR BMC050_DR_20HZ
462
463 /* PRESET MODES - REPETITIONS-XY RATES */
464 #define BMC050_LOWPOWER_REPXY 2
465 #define BMC050_REGULAR_REPXY 5
466 #define BMC050_HIGHACCURACY_REPXY 40
467
468 /* PRESET MODES - REPETITIONS-Z RATES */
469 #define BMC050_LOWPOWER_REPZ 4
470 #define BMC050_REGULAR_REPZ 13
471 #define BMC050_HIGHACCURACY_REPZ 89
472
473 /* Data Rates */
474
475 #define BMC050_DR_10HZ 0
476 #define BMC050_DR_02HZ 1
477 #define BMC050_DR_06HZ 2
478 #define BMC050_DR_08HZ 3
479 #define BMC050_DR_15HZ 4
480 #define BMC050_DR_20HZ 5
481 #define BMC050_DR_25HZ 6
482 #define BMC050_DR_30HZ 7
483
484 /*user defined Structures*/
485 struct bmm050api_mdata {
486 BMC050_S16 datax;
487 BMC050_S16 datay;
488 BMC050_S16 dataz;
489 BMC050_U16 resistance;
490 };
491
492 struct bmm050api_offset {
493 BMC050_S16 datax;
494 BMC050_S16 datay;
495 BMC050_S16 dataz;
496 };
497
498 struct bmc050 {
499 unsigned char company_id;
500 unsigned char revision_info;
501 unsigned char dev_addr;
502
503 BMC050_WR_FUNC_PTR;
504 BMC050_RD_FUNC_PTR;
505 void(*delay_msec)(BMC050_MDELAY_DATA_TYPE);
506
507 signed char dig_x1;
508 signed char dig_y1;
509
510 signed char dig_x2;
511 signed char dig_y2;
512
513 BMC050_U16 dig_z1;
514 BMC050_S16 dig_z2;
515 BMC050_S16 dig_z3;
516 BMC050_S16 dig_z4;
517
518 unsigned char dig_xy1;
519 signed char dig_xy2;
520
521 BMC050_U16 dig_xyz1;
522 };
523
524 BMC050_RETURN_FUNCTION_TYPE bmm050api_init(struct bmc050 *p_bmc050);
525 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_flipdataX(
526 BMC050_S16 *mdata_x);
527 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_flipdataY(
528 BMC050_S16 *mdata_y);
529 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_halldataZ(
530 BMC050_S16 *mdata_z);
531 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_raw_xyz(
532 struct bmm050api_mdata *mdata);
533 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_raw_xyzr(
534 struct bmm050api_mdata *mdata);
535 BMC050_RETURN_FUNCTION_TYPE bmm050api_read_mdataXYZ(
536 struct bmm050api_mdata *mdata);
537 BMC050_RETURN_FUNCTION_TYPE bmm050api_read_mdataX(
538 BMC050_S16 *mdata_x);
539 BMC050_RETURN_FUNCTION_TYPE bmm050api_read_mdataY(
540 BMC050_S16 *mdata_y);
541 BMC050_RETURN_FUNCTION_TYPE bmm050api_read_mdataZ(
542 BMC050_S16 *mdata_z);
543 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_mdataResistance(
544 BMC050_U16 *mdata_resistance);
545 BMC050_RETURN_FUNCTION_TYPE bmm050api_read_register(
546 unsigned char addr, unsigned char *data, unsigned char len);
547 BMC050_RETURN_FUNCTION_TYPE bmm050api_write_register(
548 unsigned char addr, unsigned char *data, unsigned char len);
549 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_self_test_X(
550 unsigned char *self_testx);
551 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_self_test_Y(
552 unsigned char *self_testy);
553 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_self_test_Z(
554 unsigned char *self_testz);
555 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_self_test_XYZ(
556 unsigned char *self_testxyz);
557 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_data_rdy_status(
558 unsigned char *rdy_status);
559 BMC050_S16 bmm050api_compensate_X(
560 BMC050_S16 mdata_x, BMC050_U16 data_R);
561 BMC050_S16 bmm050api_compensate_Y(
562 BMC050_S16 mdata_y, BMC050_U16 data_R);
563 BMC050_S16 bmm050api_compensate_Z(
564 BMC050_S16 mdata_z, BMC050_U16 data_R);
565 BMC050_RETURN_FUNCTION_TYPE bmm050api_init_trim_registers(void);
566 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_status_reg(
567 unsigned char *status_data);
568 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_power_control_reg(
569 unsigned char *pwr_cntl_data);
570 BMC050_RETURN_FUNCTION_TYPE bmm050api_soft_reset(void);
571 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_spi3(
572 unsigned char value);
573 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_powermode(
574 unsigned char *mode);
575 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_powermode(
576 unsigned char mode);
577 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_adv_selftest(
578 unsigned char adv_selftest);
579 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_adv_selftest(
580 unsigned char *adv_selftest);
581 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_datarate(
582 unsigned char data_rate);
583 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_datarate(
584 unsigned char *data_rate);
585 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_functional_state(
586 unsigned char functional_state);
587 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_functional_state(
588 unsigned char *functional_state);
589 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_selftest(
590 unsigned char selftest);
591 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_selftest(
592 unsigned char *selftest);
593 BMC050_RETURN_FUNCTION_TYPE bmm050api_perform_advanced_selftest(
594 BMC050_S16 *diff_z);
595 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_data_overrun_function(
596 unsigned char data_overrun_function_state);
597 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_data_overrun_function(
598 unsigned char *data_overrun_function_state);
599 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_data_overflow_function(
600 unsigned char data_overflow);
601 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_data_overflow_function(
602 unsigned char *data_overflow);
603 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_data_highthreshold_Z_function(
604 unsigned char data_highthreshold_z_function_state);
605 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_data_highthreshold_Z_function(
606 unsigned char *data_highthreshold_z_function_state);
607 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_data_highthreshold_Y_function(
608 unsigned char data_highthreshold_y_function_state);
609 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_data_highthreshold_Y_function(
610 unsigned char *data_highthreshold_y_function_state);
611 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_data_highthreshold_X_function(
612 unsigned char data_highthreshold_x_function_state);
613 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_data_highthreshold_X_function(
614 unsigned char *data_highthreshold_x_function_state);
615 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_data_lowthreshold_Z_function(
616 unsigned char data_lowthreshold_z_function_state);
617 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_data_lowthreshold_Z_function(
618 unsigned char *data_lowthreshold_z_function_state);
619 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_data_lowthreshold_Y_function(
620 unsigned char data_lowthreshold_y_function_state);
621 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_data_lowthreshold_Y_function(
622 unsigned char *data_lowthreshold_y_function_state);
623 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_data_lowthreshold_X_function(
624 unsigned char data_lowthreshold_x_function_state);
625 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_data_lowthreshold_X_function(
626 unsigned char *data_lowthreshold_x_function_state);
627 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_data_ready_function(
628 unsigned char *data_ready_function_state);
629 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_data_ready_function(
630 unsigned char data_ready_function_state);
631 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_interrupt_func(
632 unsigned char *int_func);
633 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_interrupt_func(
634 unsigned char int_func);
635 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_control_measurement_z(
636 unsigned char *enable_disable);
637 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_control_measurement_z(
638 unsigned char enable_disable);
639 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_control_measurement_y(
640 unsigned char enable_disable);
641 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_control_measurement_y(
642 unsigned char *enable_disable);
643 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_control_measurement_x(
644 unsigned char enable_disable);
645 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_control_measurement_x(
646 unsigned char *enable_disable);
647 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_DR_polarity(
648 unsigned char dr_polarity_select);
649 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_DR_polarity(
650 unsigned char *dr_polarity_select);
651 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_interrupt_latch(
652 unsigned char interrupt_latch_select);
653 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_interrupt_latch(
654 unsigned char *interrupt_latch_select);
655 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_intpin_polarity(
656 unsigned char int_polarity_select);
657 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_intpin_polarity(
658 unsigned char *int_polarity_select);
659 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_low_threshold(
660 BMC050_S16 *low_threshold);
661 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_low_threshold(
662 BMC050_S16 low_threshold);
663 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_high_threshold(
664 BMC050_S16 *high_threshold);
665 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_high_threshold(
666 BMC050_S16 high_threshold);
667 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_repetitions_XY(
668 unsigned char *no_repetitions_xy);
669 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_repetitions_XY(
670 unsigned char no_repetitions_xy);
671 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_repetitions_Z(
672 unsigned char *no_repetitions_z);
673 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_repetitions_Z(
674 unsigned char no_repetitions_z);
675 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_presetmode(unsigned char *mode);
676
677 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_presetmode(unsigned char mode);
678
679 static void bmm050_restore_hw_cfg(struct i2c_client *client);
680 static struct bmc050 *p_bmc050;
681 static int bmm050_local_init(void);
682 static int bmm050_remove(void);
683
684 static int bmm050_init_flag =-1; // 0<==>OK -1 <==> fail
685
686 static struct mag_init_info bmm050_init_info = {
687 .name = "bmm050",
688 .init = bmm050_local_init,
689 .uninit = bmm050_remove,
690
691 };
692
693
694
695 BMC050_RETURN_FUNCTION_TYPE bmm050api_init(struct bmc050 *bmc050)
696 {
697 BMC050_RETURN_FUNCTION_TYPE comres = 0;
698 unsigned char a_data_u8r[2];
699 p_bmc050 = bmc050;
700
701 p_bmc050->dev_addr = BMC050_I2C_ADDRESS;
702
703 /* set device from suspend into sleep mode */
704 bmm050api_set_powermode(BMC050_ON);
705
706 /* wait two millisecond for bmc to settle */
707 p_bmc050->delay_msec(BMC050_DELAY_SETTLING_TIME);
708
709 /*Read CHIP_ID and REv. info */
710 comres = p_bmc050->BMC050_BUS_READ_FUNC(p_bmc050->dev_addr,
711 BMC050_CHIP_ID, a_data_u8r, 2);
712 p_bmc050->company_id = a_data_u8r[0];
713 p_bmc050->revision_info = a_data_u8r[1];
714
715 /* Function to initialise trim values */
716 bmm050api_init_trim_registers();
717 return comres;
718 }
719
720 BMC050_RETURN_FUNCTION_TYPE bmm050api_init_trim_registers(void)
721 {
722 BMC050_RETURN_FUNCTION_TYPE comres = 0;
723 unsigned char a_data_u8r[2];
724 comres = p_bmc050->BMC050_BUS_READ_FUNC(p_bmc050->dev_addr,
725 BMC050_DIG_X1, (unsigned char *)&p_bmc050->dig_x1, 1);
726 comres |= p_bmc050->BMC050_BUS_READ_FUNC(p_bmc050->dev_addr,
727 BMC050_DIG_Y1, (unsigned char *)&p_bmc050->dig_y1, 1);
728 comres |= p_bmc050->BMC050_BUS_READ_FUNC(p_bmc050->dev_addr,
729 BMC050_DIG_X2, (unsigned char *)&p_bmc050->dig_x2, 1);
730 comres |= p_bmc050->BMC050_BUS_READ_FUNC(p_bmc050->dev_addr,
731 BMC050_DIG_Y2, (unsigned char *)&p_bmc050->dig_y2, 1);
732 comres |= p_bmc050->BMC050_BUS_READ_FUNC(p_bmc050->dev_addr,
733 BMC050_DIG_XY1, (unsigned char *)&p_bmc050->dig_xy1, 1);
734 comres |= p_bmc050->BMC050_BUS_READ_FUNC(p_bmc050->dev_addr,
735 BMC050_DIG_XY2, (unsigned char *)&p_bmc050->dig_xy2, 1);
736
737 /* shorts can not be recasted into (unsigned char*)
738 * due to possible mixup between trim data
739 * arrangement and memory arrangement */
740
741 comres |= p_bmc050->BMC050_BUS_READ_FUNC(p_bmc050->dev_addr,
742 BMC050_DIG_Z1_LSB, a_data_u8r, 2);
743 p_bmc050->dig_z1 = (BMC050_U16)((((BMC050_U16)((unsigned char)
744 a_data_u8r[1])) <<
745 SHIFT_LEFT_8_POSITION) | a_data_u8r[0]);
746
747 comres |= p_bmc050->BMC050_BUS_READ_FUNC(p_bmc050->dev_addr,
748 BMC050_DIG_Z2_LSB, a_data_u8r, 2);
749 p_bmc050->dig_z2 = (BMC050_S16)((((BMC050_S16)(
750 (signed char)a_data_u8r[1])) <<
751 SHIFT_LEFT_8_POSITION) | a_data_u8r[0]);
752
753 comres |= p_bmc050->BMC050_BUS_READ_FUNC(p_bmc050->dev_addr,
754 BMC050_DIG_Z3_LSB, a_data_u8r, 2);
755 p_bmc050->dig_z3 = (BMC050_S16)((((BMC050_S16)(
756 (signed char)a_data_u8r[1])) <<
757 SHIFT_LEFT_8_POSITION) | a_data_u8r[0]);
758
759 comres |= p_bmc050->BMC050_BUS_READ_FUNC(p_bmc050->dev_addr,
760 BMC050_DIG_Z4_LSB, a_data_u8r, 2);
761 p_bmc050->dig_z4 = (BMC050_S16)((((BMC050_S16)(
762 (signed char)a_data_u8r[1])) <<
763 SHIFT_LEFT_8_POSITION) | a_data_u8r[0]);
764
765 comres |= p_bmc050->BMC050_BUS_READ_FUNC(p_bmc050->dev_addr,
766 BMC050_DIG_XYZ1_LSB, a_data_u8r, 2);
767 a_data_u8r[1] = BMC050_GET_BITSLICE(a_data_u8r[1], BMC050_DIG_XYZ1_MSB);
768 p_bmc050->dig_xyz1 = (BMC050_U16)((((BMC050_U16)
769 ((unsigned char)a_data_u8r[1])) <<
770 SHIFT_LEFT_8_POSITION) | a_data_u8r[0]);
771 return comres;
772 }
773
774
775 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_datarate(unsigned char *data_rate)
776 {
777 BMC050_RETURN_FUNCTION_TYPE comres = 0;
778 unsigned char v_data_u8r;
779 if (p_bmc050 == BMC050_NULL) {
780 comres = E_BMC050_NULL_PTR;
781 } else {
782 comres = p_bmc050->BMC050_BUS_READ_FUNC(
783 p_bmc050->dev_addr,
784 BMC050_CNTL_DR__REG,
785 &v_data_u8r, 1);
786 *data_rate = BMC050_GET_BITSLICE(v_data_u8r,
787 BMC050_CNTL_DR);
788 }
789 return comres;
790 }
791
792
793 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_datarate(unsigned char data_rate)
794 {
795 BMC050_RETURN_FUNCTION_TYPE comres = 0;
796 unsigned char v_data1_u8r;
797 if (p_bmc050 == BMC050_NULL) {
798 comres = E_BMC050_NULL_PTR;
799 } else {
800 comres = p_bmc050->BMC050_BUS_READ_FUNC(
801 p_bmc050->dev_addr,
802 BMC050_CNTL_DR__REG,
803 &v_data1_u8r, 1);
804 v_data1_u8r = BMC050_SET_BITSLICE(v_data1_u8r,
805 BMC050_CNTL_DR, data_rate);
806 comres |= p_bmc050->BMC050_BUS_WRITE_FUNC(
807 p_bmc050->dev_addr,
808 BMC050_CNTL_DR__REG,
809 &v_data1_u8r, 1);
810 }
811 return comres;
812 }
813
814
815 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_powermode(unsigned char *mode)
816 {
817 BMC050_RETURN_FUNCTION_TYPE comres = 0;
818 unsigned char v_data_u8r;
819 if (p_bmc050 == BMC050_NULL) {
820 comres = E_BMC050_NULL_PTR;
821 } else {
822 comres = p_bmc050->BMC050_BUS_READ_FUNC(
823 p_bmc050->dev_addr,
824 BMC050_POWER_CNTL_PCB__REG,
825 &v_data_u8r, 1);
826 *mode = BMC050_GET_BITSLICE(v_data_u8r,
827 BMC050_POWER_CNTL_PCB);
828 }
829 return comres;
830 }
831
832 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_powermode(unsigned char mode)
833 {
834 BMC050_RETURN_FUNCTION_TYPE comres = 0;
835 unsigned char v_data_u8r;
836 if (p_bmc050 == BMC050_NULL) {
837 comres = E_BMC050_NULL_PTR;
838 } else {
839 comres = p_bmc050->BMC050_BUS_READ_FUNC(
840 p_bmc050->dev_addr,
841 BMC050_POWER_CNTL_PCB__REG,
842 &v_data_u8r, 1);
843 v_data_u8r = BMC050_SET_BITSLICE(v_data_u8r,
844 BMC050_POWER_CNTL_PCB, mode);
845 comres |= p_bmc050->BMC050_BUS_WRITE_FUNC(
846 p_bmc050->dev_addr,
847 BMC050_POWER_CNTL_PCB__REG,
848 &v_data_u8r, 1);
849 }
850 return comres;
851 }
852
853 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_functional_state(
854 unsigned char *functional_state)
855 {
856 BMC050_RETURN_FUNCTION_TYPE comres = 0;
857 unsigned char v_data_u8r;
858 if (p_bmc050 == BMC050_NULL) {
859 comres = E_BMC050_NULL_PTR;
860 } else {
861 comres = p_bmc050->BMC050_BUS_READ_FUNC(
862 p_bmc050->dev_addr,
863 BMC050_CNTL_OPMODE__REG,
864 &v_data_u8r, 1);
865 *functional_state = BMC050_GET_BITSLICE(
866 v_data_u8r, BMC050_CNTL_OPMODE);
867 }
868 return comres;
869 }
870
871
872 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_functional_state(
873 unsigned char functional_state)
874 {
875 BMC050_RETURN_FUNCTION_TYPE comres = 0;
876 unsigned char v_data1_u8r;
877 if (p_bmc050 == BMC050_NULL) {
878 comres = E_BMC050_NULL_PTR;
879 } else {
880 switch (functional_state) {
881 case BMC050_NORMAL_MODE:
882 comres = bmm050api_get_powermode(&v_data1_u8r);
883 if (v_data1_u8r == BMC050_OFF) {
884 comres = bmm050api_set_powermode(BMC050_ON);
885 p_bmc050->delay_msec(
886 BMC050_DELAY_SUSPEND_SLEEP);
887 }
888 {
889 comres |= p_bmc050->BMC050_BUS_READ_FUNC(
890 p_bmc050->dev_addr,
891 BMC050_CNTL_OPMODE__REG,
892 &v_data1_u8r, 1);
893 v_data1_u8r = BMC050_SET_BITSLICE(
894 v_data1_u8r,
895 BMC050_CNTL_OPMODE,
896 BMC050_NORMAL_MODE);
897 comres |= p_bmc050->BMC050_BUS_WRITE_FUNC(
898 p_bmc050->dev_addr,
899 BMC050_CNTL_OPMODE__REG,
900 &v_data1_u8r, 1);
901 }
902 break;
903 case BMC050_SUSPEND_MODE:
904 comres = bmm050api_set_powermode(BMC050_OFF);
905 break;
906 case BMC050_FORCED_MODE:
907 comres = bmm050api_get_powermode(&v_data1_u8r);
908 if (v_data1_u8r == BMC050_OFF) {
909 comres = bmm050api_set_powermode(BMC050_ON);
910 p_bmc050->delay_msec(
911 BMC050_DELAY_SUSPEND_SLEEP);
912 }
913 comres |= p_bmc050->BMC050_BUS_READ_FUNC(
914 p_bmc050->dev_addr,
915 BMC050_CNTL_OPMODE__REG,
916 &v_data1_u8r, 1);
917 v_data1_u8r = BMC050_SET_BITSLICE(
918 v_data1_u8r,
919 BMC050_CNTL_OPMODE, BMC050_ON);
920 comres |= p_bmc050->BMC050_BUS_WRITE_FUNC(
921 p_bmc050->dev_addr,
922 BMC050_CNTL_OPMODE__REG,
923 &v_data1_u8r, 1);
924 break;
925 case BMC050_SLEEP_MODE:
926 bmm050api_get_powermode(&v_data1_u8r);
927 if (v_data1_u8r == BMC050_OFF) {
928 comres = bmm050api_set_powermode(BMC050_ON);
929 p_bmc050->delay_msec(
930 BMC050_DELAY_SUSPEND_SLEEP);
931 }
932 comres |= p_bmc050->BMC050_BUS_READ_FUNC(
933 p_bmc050->dev_addr,
934 BMC050_CNTL_OPMODE__REG,
935 &v_data1_u8r, 1);
936 v_data1_u8r = BMC050_SET_BITSLICE(
937 v_data1_u8r,
938 BMC050_CNTL_OPMODE,
939 BMC050_SLEEP_MODE);
940 comres |= p_bmc050->BMC050_BUS_WRITE_FUNC(
941 p_bmc050->dev_addr,
942 BMC050_CNTL_OPMODE__REG,
943 &v_data1_u8r, 1);
944 break;
945 default:
946 comres = E_BMC050_OUT_OF_RANGE;
947 break;
948 }
949 }
950 return comres;
951 }
952
953 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_repetitions_XY(
954 unsigned char *no_repetitions_xy)
955 {
956 BMC050_RETURN_FUNCTION_TYPE comres = 0;
957 unsigned char v_data_u8r;
958 if (p_bmc050 == BMC050_NULL) {
959 comres = E_BMC050_NULL_PTR;
960 } else {
961 comres = p_bmc050->BMC050_BUS_READ_FUNC(
962 p_bmc050->dev_addr,
963 BMC050_NO_REPETITIONS_XY,
964 &v_data_u8r, 1);
965 *no_repetitions_xy = v_data_u8r;
966 }
967 return comres;
968 }
969
970 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_repetitions_XY(
971 unsigned char no_repetitions_xy)
972 {
973 BMC050_RETURN_FUNCTION_TYPE comres = 0;
974 unsigned char v_data_u8r;
975 if (p_bmc050 == BMC050_NULL) {
976 comres = E_BMC050_NULL_PTR;
977 } else {
978 v_data_u8r = no_repetitions_xy;
979 comres = p_bmc050->BMC050_BUS_WRITE_FUNC(
980 p_bmc050->dev_addr,
981 BMC050_NO_REPETITIONS_XY,
982 &v_data_u8r, 1);
983 }
984 return comres;
985 }
986
987 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_repetitions_Z(
988 unsigned char *no_repetitions_z)
989 {
990 BMC050_RETURN_FUNCTION_TYPE comres = 0;
991 unsigned char v_data_u8r;
992 if (p_bmc050 == BMC050_NULL) {
993 comres = E_BMC050_NULL_PTR;
994 } else {
995 comres = p_bmc050->BMC050_BUS_READ_FUNC(
996 p_bmc050->dev_addr,
997 BMC050_NO_REPETITIONS_Z,
998 &v_data_u8r, 1);
999 *no_repetitions_z = v_data_u8r;
1000 }
1001 return comres;
1002 }
1003
1004 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_repetitions_Z(
1005 unsigned char no_repetitions_z)
1006 {
1007 BMC050_RETURN_FUNCTION_TYPE comres = 0;
1008 unsigned char v_data_u8r;
1009 if (p_bmc050 == BMC050_NULL) {
1010 comres = E_BMC050_NULL_PTR;
1011 } else {
1012 v_data_u8r = no_repetitions_z;
1013 comres = p_bmc050->BMC050_BUS_WRITE_FUNC(p_bmc050->dev_addr,
1014 BMC050_NO_REPETITIONS_Z, &v_data_u8r, 1);
1015 }
1016 return comres;
1017 }
1018
1019
1020 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_raw_xyz(struct bmm050api_mdata *mdata)
1021 {
1022 BMC050_RETURN_FUNCTION_TYPE comres;
1023 unsigned char a_data_u8r[6];
1024 if (p_bmc050 == BMC050_NULL) {
1025 comres = E_BMC050_NULL_PTR;
1026 } else {
1027 comres = p_bmc050->BMC050_BUS_READ_FUNC(p_bmc050->dev_addr,
1028 BMC050_DATAX_LSB, a_data_u8r, 6);
1029
1030 a_data_u8r[0] = BMC050_GET_BITSLICE(a_data_u8r[0],
1031 BMC050_DATAX_LSB_VALUEX);
1032 mdata->datax = (BMC050_S16)((((BMC050_S16)
1033 ((signed char)a_data_u8r[1]))
1034 << SHIFT_LEFT_5_POSITION)
1035 | a_data_u8r[0]);
1036
1037 a_data_u8r[2] = BMC050_GET_BITSLICE(a_data_u8r[2],
1038 BMC050_DATAY_LSB_VALUEY);
1039 mdata->datay = (BMC050_S16)((((BMC050_S16)
1040 ((signed char)a_data_u8r[3]))
1041 << SHIFT_LEFT_5_POSITION)
1042 | a_data_u8r[2]);
1043
1044 a_data_u8r[4] = BMC050_GET_BITSLICE(a_data_u8r[4],
1045 BMC050_DATAZ_LSB_VALUEZ);
1046 mdata->dataz = (BMC050_S16)((((BMC050_S16)
1047 ((signed char)a_data_u8r[5]))
1048 << SHIFT_LEFT_7_POSITION)
1049 | a_data_u8r[4]);
1050 }
1051 return comres;
1052 }
1053
1054
1055 BMC050_RETURN_FUNCTION_TYPE bmm050api_read_mdataXYZ(struct bmm050api_mdata *mdata)
1056 {
1057 BMC050_RETURN_FUNCTION_TYPE comres;
1058
1059 unsigned char a_data_u8r[8];
1060
1061 struct {
1062 BMC050_S16 raw_dataX;
1063 BMC050_S16 raw_dataY;
1064 BMC050_S16 raw_dataZ;
1065 BMC050_U16 raw_dataR;
1066 } raw_dataXYZ;
1067
1068 if (p_bmc050 == BMC050_NULL) {
1069 comres = E_BMC050_NULL_PTR;
1070 } else {
1071 comres = p_bmc050->BMC050_BUS_READ_FUNC(p_bmc050->dev_addr,
1072 BMC050_DATAX_LSB, a_data_u8r, 8);
1073
1074 /* Reading data for X axis */
1075 a_data_u8r[0] = BMC050_GET_BITSLICE(a_data_u8r[0],
1076 BMC050_DATAX_LSB_VALUEX);
1077 raw_dataXYZ.raw_dataX = (BMC050_S16)((((BMC050_S16)
1078 ((signed char)a_data_u8r[1])) <<
1079 SHIFT_LEFT_5_POSITION) | a_data_u8r[0]);
1080
1081 /* Reading data for Y axis */
1082 a_data_u8r[2] = BMC050_GET_BITSLICE(a_data_u8r[2],
1083 BMC050_DATAY_LSB_VALUEY);
1084 raw_dataXYZ.raw_dataY = (BMC050_S16)((((BMC050_S16)
1085 ((signed char)a_data_u8r[3])) <<
1086 SHIFT_LEFT_5_POSITION) | a_data_u8r[2]);
1087
1088 /* Reading data for Z axis */
1089 a_data_u8r[4] = BMC050_GET_BITSLICE(a_data_u8r[4],
1090 BMC050_DATAZ_LSB_VALUEZ);
1091 raw_dataXYZ.raw_dataZ = (BMC050_S16)((((BMC050_S16)
1092 ((signed char)a_data_u8r[5])) <<
1093 SHIFT_LEFT_7_POSITION) | a_data_u8r[4]);
1094
1095 /* Reading data for Resistance*/
1096 a_data_u8r[6] = BMC050_GET_BITSLICE(a_data_u8r[6],
1097 BMC050_R_LSB_VALUE);
1098 raw_dataXYZ.raw_dataR = (BMC050_U16)((((BMC050_U16)
1099 a_data_u8r[7]) <<
1100 SHIFT_LEFT_6_POSITION) | a_data_u8r[6]);
1101
1102 /* Compensation for X axis */
1103 mdata->datax = bmm050api_compensate_X(raw_dataXYZ.raw_dataX,
1104 raw_dataXYZ.raw_dataR);
1105
1106 /* Compensation for Y axis */
1107 mdata->datay = bmm050api_compensate_Y(raw_dataXYZ.raw_dataY,
1108 raw_dataXYZ.raw_dataR);
1109
1110 /* Compensation for Z axis */
1111 mdata->dataz = bmm050api_compensate_Z(raw_dataXYZ.raw_dataZ,
1112 raw_dataXYZ.raw_dataR);
1113 }
1114 return comres;
1115 }
1116
1117 BMC050_S16 bmm050api_compensate_X(BMC050_S16 mdata_x, BMC050_U16 data_R)
1118 {
1119 BMC050_S16 inter_retval;
1120 if (mdata_x != BMC050_FLIP_OVERFLOW_ADCVAL /* no overflow */
1121 ) {
1122 inter_retval = ((BMC050_S16)(((BMC050_U16)
1123 ((((BMC050_S32)p_bmc050->dig_xyz1) << 14) /
1124 (data_R != 0 ? data_R : p_bmc050->dig_xyz1))) -
1125 ((BMC050_U16)0x4000)));
1126 inter_retval = ((BMC050_S16)((((BMC050_S32)mdata_x) *
1127 ((((((((BMC050_S32)p_bmc050->dig_xy2) *
1128 ((((BMC050_S32)inter_retval) *
1129 ((BMC050_S32)inter_retval)) >> 7)) +
1130 (((BMC050_S32)inter_retval) *
1131 ((BMC050_S32)(((BMC050_S16)p_bmc050->dig_xy1)
1132 << 7)))) >> 9) +
1133 ((BMC050_S32)0x100000)) *
1134 ((BMC050_S32)(((BMC050_S16)p_bmc050->dig_x2) +
1135 ((BMC050_S16)0xA0)))) >> 12)) >> 13)) +
1136 (((BMC050_S16)p_bmc050->dig_x1) << 3);
1137 } else {
1138 /* overflow */
1139 inter_retval = BMC050_OVERFLOW_OUTPUT;
1140 }
1141 return inter_retval;
1142 }
1143
1144 BMC050_S16 bmm050api_compensate_Y(BMC050_S16 mdata_y, BMC050_U16 data_R)
1145 {
1146 BMC050_S16 inter_retval;
1147 if (mdata_y != BMC050_FLIP_OVERFLOW_ADCVAL /* no overflow */
1148 ) {
1149 inter_retval = ((BMC050_S16)(((BMC050_U16)(((
1150 (BMC050_S32)p_bmc050->dig_xyz1) << 14) /
1151 (data_R != 0 ?
1152 data_R : p_bmc050->dig_xyz1))) -
1153 ((BMC050_U16)0x4000)));
1154 inter_retval = ((BMC050_S16)((((BMC050_S32)mdata_y) *
1155 ((((((((BMC050_S32)
1156 p_bmc050->dig_xy2) *
1157 ((((BMC050_S32) inter_retval) *
1158 ((BMC050_S32)inter_retval)) >> 7)) +
1159 (((BMC050_S32)inter_retval) *
1160 ((BMC050_S32)(((BMC050_S16)
1161 p_bmc050->dig_xy1) << 7)))) >> 9) +
1162 ((BMC050_S32)0x100000)) *
1163 ((BMC050_S32)(((BMC050_S16)p_bmc050->dig_y2)
1164 + ((BMC050_S16)0xA0))))
1165 >> 12)) >> 13)) +
1166 (((BMC050_S16)p_bmc050->dig_y1) << 3);
1167 } else {
1168 /* overflow */
1169 inter_retval = BMC050_OVERFLOW_OUTPUT;
1170 }
1171 return inter_retval;
1172 }
1173
1174 BMC050_S16 bmm050api_compensate_Z(BMC050_S16 mdata_z, BMC050_U16 data_R)
1175 {
1176 BMC050_S32 retval;
1177 if ((mdata_z != BMC050_HALL_OVERFLOW_ADCVAL) /* no overflow */
1178 ) {
1179 retval = (((((BMC050_S32)(mdata_z - p_bmc050->dig_z4)) << 15) -
1180 ((((BMC050_S32)p_bmc050->dig_z3) *
1181 ((BMC050_S32)(((BMC050_S16)data_R) -
1182 ((BMC050_S16)
1183 p_bmc050->dig_xyz1))))>>2)) /
1184 (p_bmc050->dig_z2 +
1185 ((BMC050_S16)(((((BMC050_S32)
1186 p_bmc050->dig_z1) *
1187 ((((BMC050_S16)data_R) << 1)))+
1188 (1<<15))>>16))));
1189 /* saturate result to +/- 2 mT */
1190 if (retval > BMC050_POSITIVE_SATURATION_Z) {
1191 retval = BMC050_POSITIVE_SATURATION_Z;
1192 } else {
1193 if (retval < BMC050_NEGATIVE_SATURATION_Z)
1194 retval = BMC050_NEGATIVE_SATURATION_Z;
1195 }
1196 } else {
1197 /* overflow */
1198 retval = BMC050_OVERFLOW_OUTPUT;
1199 }
1200 return (BMC050_S16)retval;
1201 }
1202
1203 BMC050_RETURN_FUNCTION_TYPE bmm050api_soft_reset(void)
1204 {
1205 BMC050_RETURN_FUNCTION_TYPE comres = 0;
1206 unsigned char v_data_u8r;
1207 if (p_bmc050 == BMC050_NULL) {
1208 comres = E_BMC050_NULL_PTR;
1209 } else {
1210 v_data_u8r = BMC050_ON;
1211
1212 comres = p_bmc050->BMC050_BUS_READ_FUNC(
1213 p_bmc050->dev_addr,
1214 BMC050_POWER_CNTL_SRST7__REG,
1215 &v_data_u8r, 1);
1216 v_data_u8r = BMC050_SET_BITSLICE(v_data_u8r,
1217 BMC050_POWER_CNTL_SRST7,
1218 BMC050_SOFT_RESET7_ON);
1219 comres |= p_bmc050->BMC050_BUS_WRITE_FUNC(
1220 p_bmc050->dev_addr,
1221 BMC050_POWER_CNTL_SRST7__REG, &v_data_u8r, 1);
1222
1223 comres |= p_bmc050->BMC050_BUS_READ_FUNC(
1224 p_bmc050->dev_addr,
1225 BMC050_POWER_CNTL_SRST1__REG,
1226 &v_data_u8r, 1);
1227 v_data_u8r = BMC050_SET_BITSLICE(v_data_u8r,
1228 BMC050_POWER_CNTL_SRST1,
1229 BMC050_SOFT_RESET1_ON);
1230 comres |= p_bmc050->BMC050_BUS_WRITE_FUNC(
1231 p_bmc050->dev_addr,
1232 BMC050_POWER_CNTL_SRST1__REG,
1233 &v_data_u8r, 1);
1234
1235 p_bmc050->delay_msec(BMC050_DELAY_SOFTRESET);
1236 }
1237 return comres;
1238 }
1239
1240
1241 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_self_test_XYZ(
1242 unsigned char *self_testxyz)
1243 {
1244 BMC050_RETURN_FUNCTION_TYPE comres = 0;
1245 unsigned char a_data_u8r[5], v_result_u8r = 0x00;
1246 if (p_bmc050 == BMC050_NULL) {
1247 comres = E_BMC050_NULL_PTR;
1248 } else {
1249 comres = p_bmc050->BMC050_BUS_READ_FUNC(
1250 p_bmc050->dev_addr, BMC050_DATAX_LSB_TESTX__REG,
1251 a_data_u8r, 5);
1252
1253 v_result_u8r = BMC050_GET_BITSLICE(a_data_u8r[4],
1254 BMC050_DATAZ_LSB_TESTZ);
1255
1256 v_result_u8r = (v_result_u8r << 1);
1257 v_result_u8r = (v_result_u8r | BMC050_GET_BITSLICE(
1258 a_data_u8r[2], BMC050_DATAY_LSB_TESTY));
1259
1260 v_result_u8r = (v_result_u8r << 1);
1261 v_result_u8r = (v_result_u8r | BMC050_GET_BITSLICE(
1262 a_data_u8r[0], BMC050_DATAX_LSB_TESTX));
1263
1264 *self_testxyz = v_result_u8r;
1265 }
1266 return comres;
1267 }
1268
1269 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_selftest(unsigned char selftest)
1270 {
1271 BMC050_RETURN_FUNCTION_TYPE comres = 0;
1272 unsigned char v_data1_u8r;
1273 if (p_bmc050 == BMC050_NULL) {
1274 comres = E_BMC050_NULL_PTR;
1275 } else {
1276 comres = p_bmc050->BMC050_BUS_READ_FUNC(
1277 p_bmc050->dev_addr, BMC050_CNTL_S_TEST__REG,
1278 &v_data1_u8r, 1);
1279 v_data1_u8r = BMC050_SET_BITSLICE(
1280 v_data1_u8r, BMC050_CNTL_S_TEST, selftest);
1281 comres |= p_bmc050->BMC050_BUS_WRITE_FUNC(
1282 p_bmc050->dev_addr, BMC050_CNTL_S_TEST__REG,
1283 &v_data1_u8r, 1);
1284 }
1285 return comres;
1286 }
1287
1288 BMC050_RETURN_FUNCTION_TYPE bmm050api_perform_advanced_selftest(
1289 BMC050_S16 *diff_z)
1290 {
1291 BMC050_RETURN_FUNCTION_TYPE comres;
1292 BMC050_S16 result_positive, result_negative;
1293 if (p_bmc050 == BMC050_NULL) {
1294 comres = E_BMC050_NULL_PTR;
1295 } else {
1296 /* set sleep mode to prepare for forced measurement.
1297 * If sensor is off, this will turn it on
1298 * and respect needed delays. */
1299 comres = bmm050api_set_functional_state(BMC050_SLEEP_MODE);
1300
1301 /* set normal accuracy mode */
1302 comres |= bmm050api_set_repetitions_Z(BMC050_LOWPOWER_REPZ);
1303 /* 14 repetitions Z in normal accuracy mode */
1304
1305 /* disable X, Y channel */
1306 comres |= bmm050api_set_control_measurement_x(
1307 BMC050_CHANNEL_DISABLE);
1308 comres |= bmm050api_set_control_measurement_y(
1309 BMC050_CHANNEL_DISABLE);
1310
1311 /* enable positive current and force a
1312 * measurement with positive field */
1313 comres |= bmm050api_set_adv_selftest(
1314 BMC050_ADVANCED_SELFTEST_POSITIVE);
1315 comres |= bmm050api_set_functional_state(BMC050_FORCED_MODE);
1316 /* wait for measurement to complete */
1317 p_bmc050->delay_msec(4);
1318
1319 /* read result from positive field measurement */
1320 comres |= bmm050api_read_mdataZ(&result_positive);
1321
1322 /* enable negative current and force a
1323 * measurement with negative field */
1324 comres |= bmm050api_set_adv_selftest(
1325 BMC050_ADVANCED_SELFTEST_NEGATIVE);
1326 comres |= bmm050api_set_functional_state(BMC050_FORCED_MODE);
1327 p_bmc050->delay_msec(4); /* wait for measurement to complete */
1328
1329 /* read result from negative field measurement */
1330 comres |= bmm050api_read_mdataZ(&result_negative);
1331
1332 /* turn off self test current */
1333 comres |= bmm050api_set_adv_selftest(
1334 BMC050_ADVANCED_SELFTEST_OFF);
1335
1336 /* enable X, Y channel */
1337 comres |= bmm050api_set_control_measurement_x(
1338 BMC050_CHANNEL_ENABLE);
1339 comres |= bmm050api_set_control_measurement_y(
1340 BMC050_CHANNEL_ENABLE);
1341
1342 /* write out difference in positive and negative field.
1343 * This should be ~ 200 mT = 3200 LSB */
1344 *diff_z = (result_positive - result_negative);
1345 }
1346 return comres;
1347 }
1348
1349 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_control_measurement_x(
1350 unsigned char enable_disable)
1351 {
1352 BMC050_RETURN_FUNCTION_TYPE comres = 0;
1353 unsigned char v_data1_u8r;
1354 if (p_bmc050 == BMC050_NULL) {
1355 comres = E_BMC050_NULL_PTR;
1356 } else {
1357 comres = p_bmc050->BMC050_BUS_READ_FUNC(
1358 p_bmc050->dev_addr,
1359 BMC050_SENS_CNTL_CHANNELX__REG,
1360 &v_data1_u8r, 1);
1361 v_data1_u8r = BMC050_SET_BITSLICE(v_data1_u8r,
1362 BMC050_SENS_CNTL_CHANNELX,
1363 enable_disable);
1364 comres |= p_bmc050->BMC050_BUS_WRITE_FUNC(
1365 p_bmc050->dev_addr,
1366 BMC050_SENS_CNTL_CHANNELX__REG,
1367 &v_data1_u8r, 1);
1368 }
1369 return comres;
1370 }
1371
1372 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_control_measurement_y(
1373 unsigned char enable_disable)
1374 {
1375 BMC050_RETURN_FUNCTION_TYPE comres = 0;
1376 unsigned char v_data1_u8r;
1377 if (p_bmc050 == BMC050_NULL) {
1378 comres = E_BMC050_NULL_PTR;
1379 } else {
1380 comres = p_bmc050->BMC050_BUS_READ_FUNC(
1381 p_bmc050->dev_addr,
1382 BMC050_SENS_CNTL_CHANNELY__REG,
1383 &v_data1_u8r, 1);
1384 v_data1_u8r = BMC050_SET_BITSLICE(
1385 v_data1_u8r,
1386 BMC050_SENS_CNTL_CHANNELY,
1387 enable_disable);
1388 comres |= p_bmc050->BMC050_BUS_WRITE_FUNC(
1389 p_bmc050->dev_addr,
1390 BMC050_SENS_CNTL_CHANNELY__REG,
1391 &v_data1_u8r, 1);
1392 }
1393 return comres;
1394 }
1395
1396 BMC050_RETURN_FUNCTION_TYPE bmm050api_set_adv_selftest(unsigned char adv_selftest)
1397 {
1398 BMC050_RETURN_FUNCTION_TYPE comres = 0;
1399 unsigned char v_data1_u8r;
1400 if (p_bmc050 == BMC050_NULL) {
1401 comres = E_BMC050_NULL_PTR;
1402 } else {
1403 switch (adv_selftest) {
1404 case BMC050_ADVANCED_SELFTEST_OFF:
1405 comres = p_bmc050->BMC050_BUS_READ_FUNC(
1406 p_bmc050->dev_addr,
1407 BMC050_CNTL_ADV_ST__REG,
1408 &v_data1_u8r, 1);
1409 v_data1_u8r = BMC050_SET_BITSLICE(
1410 v_data1_u8r,
1411 BMC050_CNTL_ADV_ST,
1412 BMC050_ADVANCED_SELFTEST_OFF);
1413 comres |= p_bmc050->BMC050_BUS_WRITE_FUNC(
1414 p_bmc050->dev_addr,
1415 BMC050_CNTL_ADV_ST__REG,
1416 &v_data1_u8r, 1);
1417 break;
1418 case BMC050_ADVANCED_SELFTEST_POSITIVE:
1419 comres = p_bmc050->BMC050_BUS_READ_FUNC(
1420 p_bmc050->dev_addr,
1421 BMC050_CNTL_ADV_ST__REG,
1422 &v_data1_u8r, 1);
1423 v_data1_u8r = BMC050_SET_BITSLICE(
1424 v_data1_u8r,
1425 BMC050_CNTL_ADV_ST,
1426 BMC050_ADVANCED_SELFTEST_POSITIVE);
1427 comres |= p_bmc050->BMC050_BUS_WRITE_FUNC(
1428 p_bmc050->dev_addr,
1429 BMC050_CNTL_ADV_ST__REG,
1430 &v_data1_u8r, 1);
1431 break;
1432 case BMC050_ADVANCED_SELFTEST_NEGATIVE:
1433 comres = p_bmc050->BMC050_BUS_READ_FUNC(
1434 p_bmc050->dev_addr,
1435 BMC050_CNTL_ADV_ST__REG,
1436 &v_data1_u8r, 1);
1437 v_data1_u8r = BMC050_SET_BITSLICE(
1438 v_data1_u8r,
1439 BMC050_CNTL_ADV_ST,
1440 BMC050_ADVANCED_SELFTEST_NEGATIVE);
1441 comres |= p_bmc050->BMC050_BUS_WRITE_FUNC(
1442 p_bmc050->dev_addr,
1443 BMC050_CNTL_ADV_ST__REG,
1444 &v_data1_u8r, 1);
1445 break;
1446 default:
1447 break;
1448 }
1449 }
1450 return comres;
1451 }
1452
1453 BMC050_RETURN_FUNCTION_TYPE bmm050api_read_mdataZ(BMC050_S16 *mdata_z)
1454 {
1455 BMC050_RETURN_FUNCTION_TYPE comres;
1456 BMC050_S16 raw_dataZ;
1457 BMC050_U16 raw_dataR;
1458 if (p_bmc050 == BMC050_NULL) {
1459 comres = E_BMC050_NULL_PTR;
1460 } else {
1461 comres = bmm050api_get_halldataZ(&raw_dataZ);
1462 comres |= bmm050api_get_mdataResistance(&raw_dataR);
1463
1464 /* Compensation for Z axis */
1465 *mdata_z = bmm050api_compensate_Z(raw_dataZ, raw_dataR);
1466 }
1467 return comres;
1468 }
1469
1470 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_halldataZ(BMC050_S16 *mdata_z)
1471 {
1472 BMC050_RETURN_FUNCTION_TYPE comres;
1473 unsigned char a_data_u8r[2];
1474 if (p_bmc050 == BMC050_NULL) {
1475 comres = E_BMC050_NULL_PTR;
1476 } else {
1477 comres = p_bmc050->BMC050_BUS_READ_FUNC(p_bmc050->dev_addr,
1478 BMC050_DATAZ_LSB, a_data_u8r, 2);
1479 a_data_u8r[0] = BMC050_GET_BITSLICE(a_data_u8r[0],
1480 BMC050_DATAZ_LSB_VALUEZ);
1481 *mdata_z = (BMC050_S16)((((BMC050_S16)
1482 ((signed char)a_data_u8r[1]))
1483 << SHIFT_LEFT_7_POSITION)
1484 | a_data_u8r[0]);
1485 }
1486 return comres;
1487 }
1488
1489 BMC050_RETURN_FUNCTION_TYPE bmm050api_get_mdataResistance(
1490 BMC050_U16 *mdata_resistance)
1491 {
1492 BMC050_RETURN_FUNCTION_TYPE comres;
1493 unsigned char a_data_u8r[2];
1494 if (p_bmc050 == BMC050_NULL) {
1495 comres = E_BMC050_NULL_PTR;
1496 } else {
1497 comres = p_bmc050->BMC050_BUS_READ_FUNC(
1498 p_bmc050->dev_addr,
1499 BMC050_R_LSB_VALUE__REG,
1500 a_data_u8r, 2);
1501 a_data_u8r[0] = BMC050_GET_BITSLICE(a_data_u8r[0],
1502 BMC050_R_LSB_VALUE);
1503 *mdata_resistance = (BMC050_U16)
1504 ((((BMC050_U16)a_data_u8r[1])
1505 << SHIFT_LEFT_6_POSITION)
1506 | a_data_u8r[0]);
1507 }
1508 return comres;
1509 }
1510
1511 /*----------------------------------------------------------------------------*/
1512 /* End of API Section */
1513 /*----------------------------------------------------------------------------*/
1514
1515 /*----------------------------------------------------------------------------*/
1516 #define DEBUG 1
1517 #define BMM050_DEV_NAME "bmm050"
1518 /*----------------------------------------------------------------------------*/
1519
1520 #define SENSOR_CHIP_ID_BMM (0x32)
1521
1522 #define BMM050_DEFAULT_DELAY 100
1523 #define BMM050_BUFSIZE 0x20
1524
1525 #define MSE_TAG "[Msensor] "
1526 #define MSE_FUN(f) printk(KERN_ERR MSE_TAG"%s\n", __FUNCTION__)
1527 #define MSE_ERR(fmt, args...) printk(KERN_ERR MSE_TAG"%s %d : "fmt, __FUNCTION__, __LINE__, ##args)
1528 #define MSE_LOG(fmt, args...) printk(KERN_INFO MSE_TAG fmt, ##args)
1529
1530 static struct i2c_client *this_client = NULL;
1531
1532 // calibration msensor and orientation data
1533 static int sensor_data[CALIBRATION_DATA_SIZE];
1534 static struct mutex sensor_data_mutex;
1535 static DECLARE_WAIT_QUEUE_HEAD(open_wq);
1536 static DECLARE_WAIT_QUEUE_HEAD(uplink_event_flag_wq);
1537
1538 static int bmm050d_delay = BMM050_DEFAULT_DELAY;
1539
1540 static atomic_t open_flag = ATOMIC_INIT(0);
1541 static atomic_t m_flag = ATOMIC_INIT(0);
1542 static atomic_t o_flag = ATOMIC_INIT(0);
1543
1544 static struct mutex uplink_event_flag_mutex;
1545 /* uplink event flag */
1546 static volatile u8 uplink_event_flag = 0;
1547 /* uplink event flag bitmap */
1548 enum {
1549 /* active */
1550 BMMDRV_ULEVT_FLAG_O_ACTIVE = 0x01,
1551 BMMDRV_ULEVT_FLAG_M_ACTIVE = 0x02,
1552 /* delay */
1553 BMMDRV_ULEVT_FLAG_O_DELAY = 0x04,
1554 BMMDRV_ULEVT_FLAG_M_DELAY = 0x08,
1555
1556 /* all */
1557 BMMDRV_ULEVT_FLAG_ALL = 0xff
1558 };
1559
1560 /*----------------------------------------------------------------------------*/
1561 /*----------------------------------------------------------------------------*/
1562 static const struct i2c_device_id bmm050_i2c_id[] = {{BMM050_DEV_NAME,0},{}};
1563 static struct i2c_board_info __initdata i2c_bmm050={ I2C_BOARD_INFO("bmm050", (0x10))};
1564
1565 /*the adapter id will be available in customization*/
1566 //static unsigned short bmm050_force[] = {0x00, BMM050_I2C_ADDR, I2C_CLIENT_END, I2C_CLIENT_END};
1567 //static const unsigned short *const bmm050_forces[] = { bmm050_force, NULL };
1568 //static struct i2c_client_address_data bmm050_addr_data = { .forces = bmm050_forces,};
1569 /*----------------------------------------------------------------------------*/
1570
1571 typedef enum {
1572 MMC_FUN_DEBUG = 0x01,
1573 MMC_DATA_DEBUG = 0X02,
1574 MMC_HWM_DEBUG = 0X04,
1575 MMC_CTR_DEBUG = 0X08,
1576 MMC_I2C_DEBUG = 0x10,
1577 } MMC_TRC;
1578
1579 /*----------------------------------------------------------------------------*/
1580 struct bmm050_i2c_data {
1581 struct i2c_client *client;
1582 struct mag_hw *hw;
1583 atomic_t layout;
1584 atomic_t trace;
1585 struct hwmsen_convert cvt;
1586
1587 struct bmc050 device;
1588
1589 u8 op_mode;
1590 u8 odr;
1591 u8 rept_xy;
1592 u8 rept_z;
1593
1594 #if defined(CONFIG_HAS_EARLYSUSPEND)
1595 struct early_suspend early_drv;
1596 #endif
1597 };
1598
1599 /*----------------------------------------------------------------------------*/
1600 static void bmm050_power(struct mag_hw *hw, unsigned int on)
1601 {
1602 static unsigned int power_on = 0;
1603
1604 if(hw->power_id != POWER_NONE_MACRO)
1605 {
1606 MSE_LOG("power %s\n", on ? "on" : "off");
1607 if(power_on == on)
1608 {
1609 MSE_LOG("ignore power control: %d\n", on);
1610 }
1611 else if(on)
1612 {
1613 if(!hwPowerOn(hw->power_id, hw->power_vol, "bmm050"))
1614 {
1615 MSE_ERR( "power on fails!!\n");
1616 }
1617 }
1618 else
1619 {
1620 if(!hwPowerDown(hw->power_id, "bmm050"))
1621 {
1622 MSE_ERR( "power off fail!!\n");
1623 }
1624 }
1625 }
1626 power_on = on;
1627 }
1628
1629 // Daemon application save the data
1630 static int ECS_SaveData(int buf[CALIBRATION_DATA_SIZE])
1631 {
1632 #if DEBUG
1633 struct bmm050_i2c_data *data = i2c_get_clientdata(this_client);
1634 #endif
1635
1636 mutex_lock(&sensor_data_mutex);
1637 switch (buf[0])
1638 {
1639 case 2: /* SENSOR_HANDLE_MAGNETIC_FIELD */
1640 memcpy(sensor_data+4, buf+1, 4*sizeof(int));
1641 break;
1642 case 3: /* SENSOR_HANDLE_ORIENTATION */
1643 memcpy(sensor_data+8, buf+1, 4*sizeof(int));
1644 break;
1645 default:
1646 break;
1647 }
1648 mutex_unlock(&sensor_data_mutex);
1649
1650 #if DEBUG
1651 if(atomic_read(&data->trace) & MMC_HWM_DEBUG)
1652 {
1653 MSE_LOG("Get daemon data: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d!\n",
1654 sensor_data[0],sensor_data[1],sensor_data[2],sensor_data[3],
1655 sensor_data[4],sensor_data[5],sensor_data[6],sensor_data[7],
1656 sensor_data[8],sensor_data[9],sensor_data[10],sensor_data[11]);
1657 }
1658 #endif
1659
1660 return 0;
1661 }
1662 /*----------------------------------------------------------------------------*/
1663 static int ECS_GetRawData(int data[3])
1664 {
1665 struct bmm050api_mdata mdata;
1666 struct bmm050_i2c_data *obj = i2c_get_clientdata(this_client);
1667 u8 databuf[2] = {BMC050_CONTROL, 0x02};
1668
1669 bmm050api_read_mdataXYZ(&mdata);
1670 //data in uT
1671 data[0] = mdata.datax/16;
1672 data[1] = mdata.datay/16;
1673 data[2] = mdata.dataz/16;
1674
1675 /* measure magnetic field for next sample */
1676 if (obj->op_mode == BMC050_SUSPEND_MODE)
1677 {
1678 /* power on firstly */
1679 bmm050api_set_powermode(BMC050_ON);
1680 }
1681 /* special treat of forced mode
1682 * for optimization */
1683 i2c_master_send(this_client, databuf, 2);
1684 obj->op_mode = BMC050_SLEEP_MODE;
1685
1686 return 0;
1687 }
1688 /*----------------------------------------------------------------------------*/
1689 /*
1690 static int ECS_GetOpenStatus(void)
1691 {
1692 wait_event_interruptible(open_wq, (atomic_read(&open_flag) != 0));
1693 return atomic_read(&open_flag);
1694 }
1695 */
1696 /*----------------------------------------------------------------------------*/
1697 static int bmm050_ReadChipInfo(char *buf, int bufsize)
1698 {
1699 if((!buf)||(bufsize <= BMM050_BUFSIZE -1))
1700 {
1701 return -1;
1702 }
1703 if(!this_client)
1704 {
1705 *buf = 0;
1706 return -2;
1707 }
1708
1709 sprintf(buf, "bmm050 Chip");
1710 return 0;
1711 }
1712 /*----------------------------------------------------------------------------*/
1713 static void bmm050_SetPowerMode(struct i2c_client *client, bool enable)
1714 {
1715 struct bmm050_i2c_data *obj = i2c_get_clientdata(client);
1716 //u8 power_mode;
1717
1718 if (enable == FALSE)
1719 {
1720 if (bmm050api_set_functional_state(BMC050_SUSPEND_MODE) != 0)
1721 {
1722 MSE_ERR("fail to suspend sensor");
1723 return;
1724 }
1725 }
1726 else
1727 {
1728 if (obj->op_mode == BMC050_SUSPEND_MODE)
1729 {
1730 obj->op_mode = BMC050_SLEEP_MODE;
1731 }
1732 bmm050_restore_hw_cfg(client);
1733 }
1734 }
1735
1736 /*----------------------------------------------------------------------------*/
1737 /* Driver Attributes Functions Section */
1738 static ssize_t show_daemon_name(struct device_driver *ddri, char *buf)
1739 {
1740 char strbuf[20];
1741 sprintf(strbuf, "bmm050d");
1742 return sprintf(buf, "%s", strbuf);
1743 }
1744
1745 /*----------------------------------------------------------------------------*/
1746 static ssize_t show_chipinfo_value(struct device_driver *ddri, char *buf)
1747 {
1748 char strbuf[BMM050_BUFSIZE];
1749 bmm050_ReadChipInfo(strbuf, BMM050_BUFSIZE);
1750 return sprintf(buf, "%s\n", strbuf);
1751 }
1752 /*----------------------------------------------------------------------------*/
1753 static ssize_t show_sensordata_value(struct device_driver *ddri, char *buf)
1754 {
1755 int sensordata[3];
1756 char strbuf[BMM050_BUFSIZE];
1757
1758 ECS_GetRawData(sensordata);
1759 sprintf(strbuf, "%d %d %d\n", sensordata[0],sensordata[1],sensordata[2]);
1760 return sprintf(buf, "%s\n", strbuf);
1761 }
1762 /*----------------------------------------------------------------------------*/
1763 static ssize_t show_posturedata_value(struct device_driver *ddri, char *buf)
1764 {
1765 int tmp[3];
1766 char strbuf[BMM050_BUFSIZE];
1767 tmp[0] = sensor_data[0] * CONVERT_O / CONVERT_O_DIV;
1768 tmp[1] = sensor_data[1] * CONVERT_O / CONVERT_O_DIV;
1769 tmp[2] = sensor_data[2] * CONVERT_O / CONVERT_O_DIV;
1770 sprintf(strbuf, "%d, %d, %d\n", tmp[0],tmp[1], tmp[2]);
1771
1772 return sprintf(buf, "%s\n", strbuf);;
1773 }
1774
1775 /*----------------------------------------------------------------------------*/
1776 static ssize_t show_layout_value(struct device_driver *ddri, char *buf)
1777 {
1778 struct bmm050_i2c_data *data = i2c_get_clientdata(this_client);
1779
1780 return sprintf(buf, "(%d, %d)\n[%+2d %+2d %+2d]\n[%+2d %+2d %+2d]\n",
1781 data->hw->direction,atomic_read(&data->layout), data->cvt.sign[0], data->cvt.sign[1],
1782 data->cvt.sign[2],data->cvt.map[0], data->cvt.map[1], data->cvt.map[2]);
1783 }
1784 /*----------------------------------------------------------------------------*/
1785 static ssize_t store_layout_value(struct device_driver *ddri, const char *buf, size_t count)
1786 {
1787 struct i2c_client *client = this_client;
1788 struct bmm050_i2c_data *data = i2c_get_clientdata(client);
1789 int layout = 0;
1790
1791 if(1 == sscanf(buf, "%d", &layout))
1792 {
1793 atomic_set(&data->layout, layout);
1794 if(!hwmsen_get_convert(layout, &data->cvt))
1795 {
1796 MSE_ERR( "HWMSEN_GET_CONVERT function error!\r\n");
1797 }
1798 else if(!hwmsen_get_convert(data->hw->direction, &data->cvt))
1799 {
1800 MSE_ERR( "invalid layout: %d, restore to %d\n", layout, data->hw->direction);
1801 }
1802 else
1803 {
1804 MSE_ERR( "invalid layout: (%d, %d)\n", layout, data->hw->direction);
1805 hwmsen_get_convert(0, &data->cvt);
1806 }
1807 }
1808 else
1809 {
1810 MSE_ERR( "invalid format = '%s'\n", buf);
1811 }
1812
1813 return count;
1814 }
1815 /*----------------------------------------------------------------------------*/
1816 static ssize_t show_status_value(struct device_driver *ddri, char *buf)
1817 {
1818 struct bmm050_i2c_data *data = i2c_get_clientdata(this_client);
1819 ssize_t len = 0;
1820
1821 if(data->hw)
1822 {
1823 len += snprintf(buf+len, PAGE_SIZE-len, "CUST: %d %d (%d %d)\n",
1824 data->hw->i2c_num, data->hw->direction, data->hw->power_id, data->hw->power_vol);
1825 }
1826 else
1827 {
1828 len += snprintf(buf+len, PAGE_SIZE-len, "CUST: NULL\n");
1829 }
1830
1831 return len;
1832 }
1833 /*----------------------------------------------------------------------------*/
1834 static ssize_t show_trace_value(struct device_driver *ddri, char *buf)
1835 {
1836 ssize_t res;
1837 struct bmm050_i2c_data *obj = i2c_get_clientdata(this_client);
1838 if(NULL == obj)
1839 {
1840 MSE_ERR( "bmm050_i2c_data is null!!\n");
1841 return 0;
1842 }
1843
1844 res = snprintf(buf, PAGE_SIZE, "0x%04X\n", atomic_read(&obj->trace));
1845 return res;
1846 }
1847 /*----------------------------------------------------------------------------*/
1848 static ssize_t store_trace_value(struct device_driver *ddri, const char *buf, size_t count)
1849 {
1850 struct bmm050_i2c_data *obj = i2c_get_clientdata(this_client);
1851 int trace;
1852 if(NULL == obj)
1853 {
1854 MSE_ERR( "bmm050_i2c_data is null!!\n");
1855 return 0;
1856 }
1857
1858 if(1 == sscanf(buf, "0x%x", &trace))
1859 {
1860 atomic_set(&obj->trace, trace);
1861 }
1862 else
1863 {
1864 MSE_ERR( "invalid content: '%s', length = %d\n", buf, count);
1865 }
1866
1867 return count;
1868 }
1869 /*----------------------------------------------------------------------------*/
1870 #define BMM050_AXIS_X 0
1871 #define BMM050_AXIS_Y 1
1872 #define BMM050_AXIS_Z 2
1873 static ssize_t show_cpsdata_value(struct device_driver *ddri, char *buf)
1874 {
1875 struct bmm050_i2c_data *obj = i2c_get_clientdata(this_client);
1876 struct bmm050api_mdata mdata;
1877 s16 mag[3];
1878
1879 bmm050api_read_mdataXYZ(&mdata);
1880
1881 /*remap coordinate*/
1882 mag[obj->cvt.map[BMM050_AXIS_X]] = obj->cvt.sign[BMM050_AXIS_X]*mdata.datax;
1883 mag[obj->cvt.map[BMM050_AXIS_Y]] = obj->cvt.sign[BMM050_AXIS_Y]*mdata.datay;
1884 mag[obj->cvt.map[BMM050_AXIS_Z]] = obj->cvt.sign[BMM050_AXIS_Z]*mdata.dataz;
1885
1886 return sprintf(buf, "%hd %hd %hd\n", mag[BMM050_AXIS_X], mag[BMM050_AXIS_Y], mag[BMM050_AXIS_Z]);
1887 }
1888 /*----------------------------------------------------------------------------*/
1889 static ssize_t show_cpsopmode_value(struct device_driver *ddri, char *buf)
1890 {
1891 //struct bmm050_i2c_data *obj = i2c_get_clientdata(this_client);
1892 u8 op_mode = 0xff;
1893 u8 power_mode;
1894
1895 bmm050api_get_powermode(&power_mode);
1896 if (power_mode)
1897 {
1898 bmm050api_get_functional_state(&op_mode);
1899 }
1900 else
1901 {
1902 op_mode = BMC050_SUSPEND_MODE;
1903 }
1904
1905 MSE_LOG("op_mode: %d", op_mode);
1906
1907 return sprintf(buf, "%d\n", op_mode);
1908 }
1909
1910 /*----------------------------------------------------------------------------*/
1911 static ssize_t store_cpsopmode_value(struct device_driver *ddri, const char *buf, size_t count)
1912 {
1913 struct bmm050_i2c_data *obj = i2c_get_clientdata(this_client);
1914 int err;
1915 long op_mode = 0;
1916
1917 err = strict_strtoul(buf, 10, &op_mode);
1918 /*
1919 if (((unsigned char)op_mode > 3) || (op_mode == obj->op_mode))
1920 {
1921 return -EINVAL;
1922 }*/
1923 if((unsigned char)op_mode > 3)
1924 {
1925 return -EINVAL;
1926 }
1927 if(op_mode == obj->op_mode)
1928 {
1929 return count;
1930 }
1931
1932
1933 if (BMC050_FORCED_MODE == op_mode)
1934 {
1935 u8 databuf[2] = {BMC050_CONTROL, 0x02};
1936
1937 if (obj->op_mode == BMC050_SUSPEND_MODE)
1938 {
1939 /* power on firstly */
1940 bmm050api_set_powermode(BMC050_ON);
1941 }
1942 /* special treat of forced mode
1943 * for optimization */
1944 i2c_master_send(this_client, databuf, 2);
1945 obj->op_mode = BMC050_SLEEP_MODE;
1946 }
1947 else
1948 {
1949 bmm050api_set_functional_state((unsigned char)op_mode);
1950 obj->op_mode = op_mode;
1951 }
1952
1953 return count;
1954 }
1955 /*----------------------------------------------------------------------------*/
1956 static ssize_t show_cpsreptxy_value(struct device_driver *ddri, char *buf)
1957 {
1958 unsigned char data = 0;
1959 u8 power_mode;
1960 int err;
1961
1962 bmm050api_get_powermode(&power_mode);
1963 if (power_mode)
1964 {
1965 err = bmm050api_get_repetitions_XY(&data);
1966 }
1967 else
1968 {
1969 err = -EIO;
1970 }
1971
1972 if (err)
1973 return err;
1974
1975 return sprintf(buf, "%d\n", data);
1976 }
1977 /*----------------------------------------------------------------------------*/
1978 static ssize_t store_cpsreptxy_value(struct device_driver *ddri, const char *buf, size_t count)
1979 {
1980 struct bmm050_i2c_data *obj = i2c_get_clientdata(this_client);
1981 unsigned long tmp = 0;
1982 int err;
1983 u8 data;
1984 u8 power_mode;
1985
1986 err = strict_strtoul(buf, 10, &tmp);
1987 if (err)
1988 return err;
1989
1990 if (tmp > 255)
1991 return -EINVAL;
1992
1993 data = (unsigned char)tmp;
1994
1995 bmm050api_get_powermode(&power_mode);
1996 if (power_mode)
1997 {
1998 err = bmm050api_set_repetitions_XY(data);
1999 if (!err)
2000 {
2001 //mdelay(BMM_I2C_WRITE_DELAY_TIME);
2002 obj->rept_xy = data;
2003 }
2004 }
2005 else
2006 {
2007 err = -EIO;
2008 }
2009
2010 if (err)
2011 return err;
2012
2013 return count;
2014 }
2015 /*----------------------------------------------------------------------------*/
2016 static ssize_t show_cpsreptz_value(struct device_driver *ddri, char *buf)
2017 {
2018 unsigned char data = 0;
2019 u8 power_mode;
2020 int err;
2021
2022 bmm050api_get_powermode(&power_mode);
2023 if (power_mode)
2024 {
2025 err = bmm050api_get_repetitions_Z(&data);
2026 }
2027 else
2028 {
2029 err = -EIO;
2030 }
2031
2032 if (err)
2033 return err;
2034
2035 return sprintf(buf, "%d\n", data);
2036 }
2037 /*----------------------------------------------------------------------------*/
2038 static ssize_t store_cpsreptz_value(struct device_driver *ddri, const char *buf, size_t count)
2039 {
2040 struct bmm050_i2c_data *obj = i2c_get_clientdata(this_client);
2041 unsigned long tmp = 0;
2042 int err;
2043 u8 data;
2044 u8 power_mode;
2045
2046 err = strict_strtoul(buf, 10, &tmp);
2047 if (err)
2048 return err;
2049
2050 if (tmp > 255)
2051 return -EINVAL;
2052
2053 data = (unsigned char)tmp;
2054
2055 bmm050api_get_powermode(&power_mode);
2056 if (power_mode)
2057 {
2058 err = bmm050api_set_repetitions_Z(data);
2059 if (!err)
2060 {
2061 //mdelay(BMM_I2C_WRITE_DELAY_TIME);
2062 obj->rept_z = data;
2063 }
2064 }
2065 else
2066 {
2067 err = -EIO;
2068 }
2069
2070 if (err)
2071 return err;
2072
2073 return count;
2074 }
2075 /*----------------------------------------------------------------------------*/
2076 static DRIVER_ATTR(daemon, S_IRUGO, show_daemon_name, NULL);
2077 static DRIVER_ATTR(chipinfo, S_IRUGO, show_chipinfo_value, NULL);
2078 static DRIVER_ATTR(sensordata, S_IRUGO, show_sensordata_value, NULL);
2079 static DRIVER_ATTR(posturedata, S_IRUGO, show_posturedata_value, NULL);
2080 static DRIVER_ATTR(layout, S_IRUGO | S_IWUSR, show_layout_value, store_layout_value);
2081 static DRIVER_ATTR(status, S_IRUGO, show_status_value, NULL);
2082 static DRIVER_ATTR(trace, S_IRUGO | S_IWUSR, show_trace_value, store_trace_value);
2083 static DRIVER_ATTR(cpsdata, S_IWUSR | S_IRUGO, show_cpsdata_value, NULL);
2084 static DRIVER_ATTR(cpsopmode, S_IRUGO | S_IWUSR, show_cpsopmode_value, store_cpsopmode_value);
2085 static DRIVER_ATTR(cpsreptxy, S_IRUGO | S_IWUSR, show_cpsreptxy_value, store_cpsreptxy_value);
2086 static DRIVER_ATTR(cpsreptz, S_IRUGO | S_IWUSR, show_cpsreptz_value, store_cpsreptz_value);
2087 /*----------------------------------------------------------------------------*/
2088 static struct driver_attribute *bmm050_attr_list[] = {
2089 &driver_attr_daemon,
2090 &driver_attr_chipinfo,
2091 &driver_attr_sensordata,
2092 &driver_attr_posturedata,
2093 &driver_attr_layout,
2094 &driver_attr_status,
2095 &driver_attr_trace,
2096 &driver_attr_cpsdata,
2097 &driver_attr_cpsopmode,
2098 &driver_attr_cpsreptxy,
2099 &driver_attr_cpsreptz,
2100 };
2101 /*----------------------------------------------------------------------------*/
2102 static int bmm050_create_attr(struct device_driver *driver)
2103 {
2104 int idx, err = 0;
2105 int num = (int)(sizeof(bmm050_attr_list)/sizeof(bmm050_attr_list[0]));
2106 if (driver == NULL)
2107 {
2108 return -EINVAL;
2109 }
2110
2111 for(idx = 0; idx < num; idx++)
2112 {
2113 if((err = driver_create_file(driver, bmm050_attr_list[idx])))
2114 {
2115 MSE_ERR( "driver_create_file (%s) = %d\n", bmm050_attr_list[idx]->attr.name, err);
2116 break;
2117 }
2118 }
2119
2120 return err;
2121 }
2122 /*----------------------------------------------------------------------------*/
2123 static int bmm050_delete_attr(struct device_driver *driver)
2124 {
2125 int idx;
2126 int num = (int)(sizeof(bmm050_attr_list)/sizeof(bmm050_attr_list[0]));
2127
2128 if(driver == NULL)
2129 {
2130 return -EINVAL;
2131 }
2132
2133 for(idx = 0; idx < num; idx++)
2134 {
2135 driver_remove_file(driver, bmm050_attr_list[idx]);
2136 }
2137
2138 return 0;
2139 }
2140
2141 /*----------------------------------------------------------------------------*/
2142 static int bmm050_open(struct inode *inode, struct file *file)
2143 {
2144 struct bmm050_i2c_data *obj = i2c_get_clientdata(this_client);
2145 int ret = -1;
2146
2147 if(atomic_read(&obj->trace) & MMC_CTR_DEBUG)
2148 {
2149 MSE_LOG("Open device node:bmm050\n");
2150 }
2151 ret = nonseekable_open(inode, file);
2152
2153 return ret;
2154 }
2155 /*----------------------------------------------------------------------------*/
2156 static int bmm050_release(struct inode *inode, struct file *file)
2157 {
2158 struct bmm050_i2c_data *obj = i2c_get_clientdata(this_client);
2159
2160 if(atomic_read(&obj->trace) & MMC_CTR_DEBUG)
2161 {
2162 MSE_LOG("Release device node:bmm050\n");
2163 }
2164 return 0;
2165 }
2166 /*----------------------------------------------------------------------------*/
2167 #define BMM_IOC_GET_EVENT_FLAG ECOMPASS_IOC_GET_OPEN_STATUS
2168 //static int bmm050_ioctl(struct inode *inode, struct file *file, unsigned int cmd,unsigned long arg)
2169 static long bmm050_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2170 {
2171 void __user *argp = (void __user *)arg;
2172
2173 /* NOTE: In this function the size of "char" should be 1-byte. */
2174 char buff[BMM050_BUFSIZE]; /* for chip information */
2175
2176 int value[CALIBRATION_DATA_SIZE]; /* for SET_YPR */
2177 int status; /* for OPEN/CLOSE_STATUS */
2178 short sensor_status; /* for Orientation and Msensor status */
2179 int vec[3] = {0};
2180 struct bmm050_i2c_data *clientdata = i2c_get_clientdata(this_client);
2181 hwm_sensor_data osensor_data;
2182 uint32_t enable;
2183
2184 switch (cmd)
2185 {
2186 case BMM_IOC_GET_EVENT_FLAG: // used by daemon only
2187 /* block if no event updated */
2188 wait_event_interruptible(uplink_event_flag_wq, (uplink_event_flag != 0));
2189 mutex_lock(&uplink_event_flag_mutex);
2190 status = uplink_event_flag;
2191 mutex_unlock(&uplink_event_flag_mutex);
2192 if(copy_to_user(argp, &status, sizeof(status)))
2193 {
2194 MSE_ERR("copy_to_user failed.");
2195 return -EFAULT;
2196 }
2197 break;
2198
2199 case ECOMPASS_IOC_GET_DELAY: //used by daemon
2200 if(copy_to_user(argp, &bmm050d_delay, sizeof(bmm050d_delay)))
2201 {
2202 MSE_ERR("copy_to_user failed.");
2203 return -EFAULT;
2204 }
2205 /* clear the flag */
2206 mutex_lock(&uplink_event_flag_mutex);
2207 if ((uplink_event_flag & BMMDRV_ULEVT_FLAG_M_DELAY) != 0)
2208 {
2209 uplink_event_flag &= ~BMMDRV_ULEVT_FLAG_M_DELAY;
2210 }
2211 else if ((uplink_event_flag & BMMDRV_ULEVT_FLAG_O_DELAY) != 0)
2212 {
2213 uplink_event_flag &= ~BMMDRV_ULEVT_FLAG_O_DELAY;
2214 }
2215 mutex_unlock(&uplink_event_flag_mutex);
2216 /* wake up the wait queue */
2217 wake_up(&uplink_event_flag_wq);
2218 break;
2219
2220 case ECOMPASS_IOC_SET_YPR: //used by daemon
2221 if(argp == NULL)
2222 {
2223 MSE_ERR("invalid argument.");
2224 return -EINVAL;
2225 }
2226 if(copy_from_user(value, argp, sizeof(value)))
2227 {
2228 MSE_ERR("copy_from_user failed.");
2229 return -EFAULT;
2230 }
2231 ECS_SaveData(value);
2232 break;
2233
2234 case ECOMPASS_IOC_GET_MFLAG: //used by daemon
2235 sensor_status = atomic_read(&m_flag);
2236 if(copy_to_user(argp, &sensor_status, sizeof(sensor_status)))
2237 {
2238 MSE_ERR("copy_to_user failed.");
2239 return -EFAULT;
2240 }
2241 /* clear the flag */
2242 mutex_lock(&uplink_event_flag_mutex);
2243 if ((uplink_event_flag & BMMDRV_ULEVT_FLAG_M_ACTIVE) != 0)
2244 {
2245 uplink_event_flag &= ~BMMDRV_ULEVT_FLAG_M_ACTIVE;
2246 }
2247 mutex_unlock(&uplink_event_flag_mutex);
2248 /* wake up the wait queue */
2249 wake_up(&uplink_event_flag_wq);
2250 break;
2251
2252 case ECOMPASS_IOC_GET_OFLAG: //used by daemon
2253 sensor_status = atomic_read(&o_flag);
2254 if(copy_to_user(argp, &sensor_status, sizeof(sensor_status)))
2255 {
2256 MSE_ERR("copy_to_user failed.");
2257 return -EFAULT;
2258 }
2259 /* clear the flag */
2260 mutex_lock(&uplink_event_flag_mutex);
2261 if ((uplink_event_flag & BMMDRV_ULEVT_FLAG_O_ACTIVE) != 0)
2262 {
2263 uplink_event_flag &= ~BMMDRV_ULEVT_FLAG_O_ACTIVE;
2264 }
2265 mutex_unlock(&uplink_event_flag_mutex);
2266 /* wake up the wait queue */
2267 wake_up(&uplink_event_flag_wq);
2268 break;
2269
2270
2271 case MSENSOR_IOCTL_READ_CHIPINFO: //reserved
2272 if(argp == NULL)
2273 {
2274 MSE_ERR( "IO parameter pointer is NULL!\r\n");
2275 break;
2276 }
2277
2278 bmm050_ReadChipInfo(buff, BMM050_BUFSIZE);
2279 if(copy_to_user(argp, buff, strlen(buff)+1))
2280 {
2281 return -EFAULT;
2282 }
2283 break;
2284
2285 case MSENSOR_IOCTL_READ_SENSORDATA: //used by MTK ftm or engineering mode
2286 if(argp == NULL)
2287 {
2288 MSE_ERR( "IO parameter pointer is NULL!\r\n");
2289 break;
2290 }
2291 ECS_GetRawData(vec);
2292 sprintf(buff, "%x %x %x", vec[0], vec[1], vec[2]);
2293 if(copy_to_user(argp, buff, strlen(buff)+1))
2294 {
2295 return -EFAULT;
2296 }
2297 break;
2298
2299 case ECOMPASS_IOC_GET_LAYOUT: //used by daemon ?
2300 status = atomic_read(&clientdata->layout);
2301 if(copy_to_user(argp, &status, sizeof(status)))
2302 {
2303 MSE_ERR("copy_to_user failed.");
2304 return -EFAULT;
2305 }
2306 break;
2307
2308 case MSENSOR_IOCTL_SENSOR_ENABLE: //used by MTK ftm
2309 if(argp == NULL)
2310 {
2311 MSE_ERR( "IO parameter pointer is NULL!\r\n");
2312 break;
2313 }
2314 if(copy_from_user(&enable, argp, sizeof(enable)))
2315 {
2316 MSE_ERR("copy_from_user failed.");
2317 return -EFAULT;
2318 }
2319 else
2320 {
2321 printk( "MSENSOR_IOCTL_SENSOR_ENABLE enable=%d!\r\n",enable);
2322 if(1 == enable)
2323 {
2324 atomic_set(&o_flag, 1);
2325 atomic_set(&open_flag, 1);
2326 }
2327 else
2328 {
2329 atomic_set(&o_flag, 0);
2330 if(atomic_read(&m_flag) == 0)
2331 {
2332 atomic_set(&open_flag, 0);
2333 }
2334 }
2335 wake_up(&open_wq);
2336
2337 /* set the flag */
2338 mutex_lock(&uplink_event_flag_mutex);
2339 uplink_event_flag |= BMMDRV_ULEVT_FLAG_O_ACTIVE;
2340 mutex_unlock(&uplink_event_flag_mutex);
2341 /* wake up the wait queue */
2342 wake_up(&uplink_event_flag_wq);
2343 }
2344 break;
2345
2346 case MSENSOR_IOCTL_READ_FACTORY_SENSORDATA: //used by MTK ftm
2347 if(argp == NULL)
2348 {
2349 MSE_ERR( "IO parameter pointer is NULL!\r\n");
2350 break;
2351 }
2352
2353 mutex_lock(&sensor_data_mutex);
2354
2355 osensor_data.values[0] = sensor_data[8];
2356 osensor_data.values[1] = sensor_data[9];
2357 osensor_data.values[2] = sensor_data[10];
2358 osensor_data.status = sensor_data[11];
2359 osensor_data.value_divide = CONVERT_O_DIV;
2360
2361 mutex_unlock(&sensor_data_mutex);
2362 if(copy_to_user(argp, &osensor_data, sizeof(hwm_sensor_data)))
2363 {
2364 return -EFAULT;
2365 }
2366 break;
2367
2368 default:
2369 MSE_ERR( "%s not supported = 0x%04x", __FUNCTION__, cmd);
2370 return -ENOIOCTLCMD;
2371 break;
2372 }
2373
2374 return 0;
2375 }
2376 /*----------------------------------------------------------------------------*/
2377 static struct file_operations bmm050_fops = {
2378 //.owner = THIS_MODULE,
2379 .open = bmm050_open,
2380 .release = bmm050_release,
2381 .unlocked_ioctl = bmm050_unlocked_ioctl,
2382 };
2383 /*----------------------------------------------------------------------------*/
2384 static struct miscdevice bmm050_device = {
2385 .minor = MISC_DYNAMIC_MINOR,
2386 .name = "msensor",
2387 .fops = &bmm050_fops,
2388 };
2389 /*----------------------------------------------------------------------------*/
2390 static int bmm050_operate(void* self, uint32_t command, void* buff_in, int size_in,
2391 void* buff_out, int size_out, int* actualout)
2392 {
2393 int err = 0;
2394 int value;
2395 hwm_sensor_data* msensor_data;
2396
2397 #if DEBUG
2398 struct i2c_client *client = this_client;
2399 struct bmm050_i2c_data *data = i2c_get_clientdata(client);
2400 #endif
2401
2402 #if DEBUG
2403 if(atomic_read(&data->trace) & MMC_FUN_DEBUG)
2404 {
2405 MSE_FUN();
2406 }
2407 #endif
2408 switch (command)
2409 {
2410 case SENSOR_DELAY:
2411 if((buff_in == NULL) || (size_in < sizeof(int)))
2412 {
2413 MSE_ERR( "Set delay parameter error!\n");
2414 err = -EINVAL;
2415 }
2416 else
2417 {
2418 value = *(int *)buff_in;
2419 if(value <= 20)
2420 {
2421 bmm050d_delay = 20;
2422 }
2423 else
2424 {
2425 bmm050d_delay = value;
2426 }
2427 /* set the flag */
2428 mutex_lock(&uplink_event_flag_mutex);
2429 uplink_event_flag |= BMMDRV_ULEVT_FLAG_M_DELAY;
2430 mutex_unlock(&uplink_event_flag_mutex);
2431 /* wake up the wait queue */
2432 wake_up(&uplink_event_flag_wq);
2433 }
2434 break;
2435
2436 case SENSOR_ENABLE:
2437 if((buff_in == NULL) || (size_in < sizeof(int)))
2438 {
2439 MSE_ERR( "Enable sensor parameter error!\n");
2440 err = -EINVAL;
2441 }
2442 else
2443 {
2444
2445 value = *(int *)buff_in;
2446
2447 if(value == 1)
2448 {
2449 atomic_set(&m_flag, 1);
2450 atomic_set(&open_flag, 1);
2451 }
2452 else
2453 {
2454 atomic_set(&m_flag, 0);
2455 if(atomic_read(&o_flag) == 0)
2456 {
2457 atomic_set(&open_flag, 0);
2458 }
2459 }
2460 wake_up(&open_wq);
2461
2462 bmm050_SetPowerMode(this_client, (value == 1));
2463
2464 /* set the flag */
2465 mutex_lock(&uplink_event_flag_mutex);
2466 uplink_event_flag |= BMMDRV_ULEVT_FLAG_M_ACTIVE;
2467 mutex_unlock(&uplink_event_flag_mutex);
2468 /* wake up the wait queue */
2469 wake_up(&uplink_event_flag_wq);
2470 }
2471 break;
2472
2473 case SENSOR_GET_DATA:
2474 if((buff_out == NULL) || (size_out< sizeof(hwm_sensor_data)))
2475 {
2476 MSE_ERR( "get sensor data parameter error!\n");
2477 err = -EINVAL;
2478 }
2479 else
2480 {
2481 msensor_data = (hwm_sensor_data *)buff_out;
2482 mutex_lock(&sensor_data_mutex);
2483
2484 msensor_data->values[0] = sensor_data[4];
2485 msensor_data->values[1] = sensor_data[5];
2486 msensor_data->values[2] = sensor_data[6];
2487 msensor_data->status = sensor_data[7];
2488 msensor_data->value_divide = CONVERT_M_DIV;
2489
2490 mutex_unlock(&sensor_data_mutex);
2491 #if DEBUG
2492 if(atomic_read(&data->trace) & MMC_HWM_DEBUG)
2493 {
2494 MSE_LOG("Hwm get m-sensor data: %d, %d, %d. divide %d, status %d!\n",
2495 msensor_data->values[0],msensor_data->values[1],msensor_data->values[2],
2496 msensor_data->value_divide,msensor_data->status);
2497 }
2498 #endif
2499 }
2500 break;
2501 default:
2502 MSE_ERR( "msensor operate function no this parameter %d!\n", command);
2503 err = -1;
2504 break;
2505 }
2506
2507 return err;
2508 }
2509
2510 /*----------------------------------------------------------------------------*/
2511 int bmm050_orientation_operate(void* self, uint32_t command, void* buff_in, int size_in,
2512 void* buff_out, int size_out, int* actualout)
2513 {
2514 int err = 0;
2515 int value;
2516 hwm_sensor_data* osensor_data;
2517 #if DEBUG
2518 struct i2c_client *client = this_client;
2519 struct bmm050_i2c_data *data = i2c_get_clientdata(client);
2520 #endif
2521
2522 #if DEBUG
2523 if(atomic_read(&data->trace) & MMC_FUN_DEBUG)
2524 {
2525 MSE_FUN();
2526 }
2527 #endif
2528
2529 switch (command)
2530 {
2531 case SENSOR_DELAY:
2532 if((buff_in == NULL) || (size_in < sizeof(int)))
2533 {
2534 MSE_ERR( "Set delay parameter error!\n");
2535 err = -EINVAL;
2536 }
2537 else
2538 {
2539 value = *(int *)buff_in;
2540 if(value <= 20)
2541 {
2542 bmm050d_delay = 20;
2543 }
2544 else
2545 {
2546 bmm050d_delay = value;
2547 }
2548 /* set the flag */
2549 mutex_lock(&uplink_event_flag_mutex);
2550 uplink_event_flag |= BMMDRV_ULEVT_FLAG_O_DELAY;
2551 mutex_unlock(&uplink_event_flag_mutex);
2552 /* wake up the wait queue */
2553 wake_up(&uplink_event_flag_wq);
2554 }
2555 break;
2556
2557 case SENSOR_ENABLE:
2558 if((buff_in == NULL) || (size_in < sizeof(int)))
2559 {
2560 MSE_ERR( "Enable sensor parameter error!\n");
2561 err = -EINVAL;
2562 }
2563 else
2564 {
2565
2566 value = *(int *)buff_in;
2567
2568 if(value == 1)
2569 {
2570 atomic_set(&o_flag, 1);
2571 atomic_set(&open_flag, 1);
2572 }
2573 else
2574 {
2575 atomic_set(&o_flag, 0);
2576 if(atomic_read(&m_flag) == 0)
2577 {
2578 atomic_set(&open_flag, 0);
2579 }
2580 }
2581 wake_up(&open_wq);
2582
2583 /* set the flag */
2584 mutex_lock(&uplink_event_flag_mutex);
2585 uplink_event_flag |= BMMDRV_ULEVT_FLAG_O_ACTIVE;
2586 mutex_unlock(&uplink_event_flag_mutex);
2587 /* wake up the wait queue */
2588 wake_up(&uplink_event_flag_wq);
2589 }
2590 break;
2591
2592 case SENSOR_GET_DATA:
2593 if((buff_out == NULL) || (size_out< sizeof(hwm_sensor_data)))
2594 {
2595 MSE_ERR( "get sensor data parameter error!\n");
2596 err = -EINVAL;
2597 }
2598 else
2599 {
2600 osensor_data = (hwm_sensor_data *)buff_out;
2601 mutex_lock(&sensor_data_mutex);
2602
2603 osensor_data->values[0] = sensor_data[8];
2604 osensor_data->values[1] = sensor_data[9];
2605 osensor_data->values[2] = sensor_data[10];
2606 osensor_data->status = sensor_data[11];
2607 osensor_data->value_divide = CONVERT_O_DIV;
2608
2609 mutex_unlock(&sensor_data_mutex);
2610 #if DEBUG
2611 if(atomic_read(&data->trace) & MMC_HWM_DEBUG)
2612 {
2613 MSE_LOG("Hwm get o-sensor data: %d, %d, %d. divide %d, status %d!\n",
2614 osensor_data->values[0],osensor_data->values[1],osensor_data->values[2],
2615 osensor_data->value_divide,osensor_data->status);
2616 }
2617 #endif
2618 }
2619 break;
2620 default:
2621 MSE_ERR( "osensor operate function no this parameter %d!\n", command);
2622 err = -1;
2623 break;
2624 }
2625
2626 return err;
2627 }
2628
2629 /*----------------------------------------------------------------------------*/
2630 static void bmm050_restore_hw_cfg(struct i2c_client *client)
2631 {
2632 struct bmm050_i2c_data *obj = i2c_get_clientdata(client);
2633
2634 if (obj->op_mode > 3)
2635 {
2636 obj->op_mode = BMC050_SLEEP_MODE;
2637 }
2638 bmm050api_set_functional_state(obj->op_mode);
2639
2640 bmm050api_set_datarate(obj->odr);
2641 //mdelay(BMM_I2C_WRITE_DELAY_TIME);
2642
2643 bmm050api_set_repetitions_XY(obj->rept_xy);
2644 //mdelay(BMM_I2C_WRITE_DELAY_TIME);
2645
2646 bmm050api_set_repetitions_Z(obj->rept_z);
2647 //mdelay(BMM_I2C_WRITE_DELAY_TIME);
2648 }
2649
2650 /*----------------------------------------------------------------------------*/
2651 #ifndef CONFIG_HAS_EARLYSUSPEND
2652 /*----------------------------------------------------------------------------*/
2653 static int bmm050_suspend(struct i2c_client *client, pm_message_t msg)
2654 {
2655 struct bmm050_i2c_data *obj = i2c_get_clientdata(client)
2656
2657
2658 if(msg.event == PM_EVENT_SUSPEND)
2659 {
2660 bmm050_SetPowerMode(obj->client, FALSE);
2661 bmm050_power(obj->hw, 0);
2662 }
2663 return 0;
2664 }
2665 /*----------------------------------------------------------------------------*/
2666 static int bmm050_resume(struct i2c_client *client)
2667 {
2668 struct bmm050_i2c_data *obj = i2c_get_clientdata(client)
2669
2670 bmm050_power(obj->hw, 1);
2671 bmm050_SetPowerMode(obj->client, TRUE);
2672 return 0;
2673 }
2674 /*----------------------------------------------------------------------------*/
2675 #else /*CONFIG_HAS_EARLY_SUSPEND is defined*/
2676 /*----------------------------------------------------------------------------*/
2677 static void bmm050_early_suspend(struct early_suspend *h)
2678 {
2679 struct bmm050_i2c_data *obj = container_of(h, struct bmm050_i2c_data, early_drv);
2680 //u8 power_mode;
2681 //int err = 0;
2682
2683 if(NULL == obj)
2684 {
2685 MSE_ERR( "null pointer!!\n");
2686 return;
2687 }
2688
2689 bmm050_SetPowerMode(obj->client, FALSE);
2690 bmm050_power(obj->hw, 0);
2691 }
2692 /*----------------------------------------------------------------------------*/
2693 static void bmm050_late_resume(struct early_suspend *h)
2694 {
2695 struct bmm050_i2c_data *obj = container_of(h, struct bmm050_i2c_data, early_drv);
2696
2697
2698 if(NULL == obj)
2699 {
2700 MSE_ERR( "null pointer!!\n");
2701 return;
2702 }
2703
2704 bmm050_power(obj->hw, 1);
2705 bmm050_SetPowerMode(obj->client, TRUE);
2706 }
2707 #endif /*CONFIG_HAS_EARLYSUSPEND*/
2708 /*----------------------------------------------------------------------------*/
2709 #define BMM_MAX_RETRY_WAKEUP (5)
2710 #define BMM_I2C_WRITE_DELAY_TIME (1)
2711 static int bmm050_wakeup(struct i2c_client *client)
2712 {
2713 int err = 0;
2714 int try_times = BMM_MAX_RETRY_WAKEUP;
2715 u8 data[2] = {BMC050_POWER_CNTL, 0x01};
2716 u8 dummy;
2717
2718 MSE_LOG("waking up the chip...");
2719
2720 while (try_times) {
2721 err = i2c_master_send(client, data, 2);
2722 mdelay(BMM_I2C_WRITE_DELAY_TIME);
2723 dummy = 0;
2724 err = hwmsen_read_block(client, BMC050_POWER_CNTL, &dummy, 1);
2725 if (data[1] == dummy)
2726 {
2727 break;
2728 }
2729 try_times--;
2730 }
2731
2732 MSE_LOG("wake up result: %s, tried times: %d",
2733 (try_times > 0) ? "succeed" : "fail",
2734 BMM_MAX_RETRY_WAKEUP - try_times + 1);
2735
2736 err = (try_times > 0) ? 0 : -1;
2737
2738 return err;
2739 }
2740 /*----------------------------------------------------------------------------*/
2741 static int bmm050_checkchipid(struct i2c_client *client)
2742 {
2743 //int err = 0;
2744 u8 chip_id = 0;
2745
2746 MSE_ERR( "ivy bmm050_checkchipid22");
2747 hwmsen_read_block(client, BMC050_CHIP_ID, &chip_id, 1);
2748 MSE_LOG("read chip id result: %#x", chip_id);
2749
2750 if ((chip_id & 0xff) != SENSOR_CHIP_ID_BMM)
2751 {
2752 return -1;
2753 }
2754 else
2755 {
2756 return 0;
2757 }
2758 }
2759 /*----------------------------------------------------------------------------*/
2760 static char bmm050_i2c_read_wrapper(u8 dev_addr, u8 reg_addr, u8 *data, u8 len)
2761 {
2762 return hwmsen_read_block(this_client, reg_addr, data, len);
2763 }
2764 /*----------------------------------------------------------------------------*/
2765 static char bmm050_i2c_write_wrapper(u8 dev_addr, u8 reg_addr, u8 *data, u8 len)
2766 {
2767 u8 buff[BMM050_BUFSIZE + 1];
2768
2769 if (len > BMM050_BUFSIZE)
2770 {
2771 return -1;
2772 }
2773
2774 buff[0] = reg_addr;
2775 memcpy(buff+1, data, len);
2776 if (i2c_master_send(this_client, buff, len+1) != (len+1))
2777 {
2778 /* I2C transfer error */
2779 return -EIO;
2780 }
2781 else
2782 {
2783 return 0;
2784 }
2785 }
2786 /*----------------------------------------------------------------------------*/
2787 static void bmm050_delay(u32 msec)
2788 {
2789 mdelay(msec);
2790 }
2791 /*----------------------------------------------------------------------------*/
2792 static int bmm050_init_client(struct i2c_client *client)
2793 {
2794 struct bmm050_i2c_data *obj = i2c_get_clientdata(client);
2795 int res = 0;
2796 MSE_ERR( "ivy bmm050_init_client");
2797
2798 res = bmm050_wakeup(client);
2799 if (res < 0)
2800 {
2801 return res;
2802 }
2803 MSE_ERR( "ivy bmm050_checkchipid");
2804 res = bmm050_checkchipid(client);
2805 if(res < 0)
2806 {
2807 return res;
2808 }
2809 MSE_LOG("check chip ID ok");
2810
2811 //bmm050 api init
2812 obj->device.bus_read = bmm050_i2c_read_wrapper;
2813 obj->device.bus_write = bmm050_i2c_write_wrapper;
2814 obj->device.delay_msec = bmm050_delay;
2815 bmm050api_init(&obj->device);
2816
2817 /* now it's power on which is considered as resuming from suspend */
2818 obj->op_mode = BMC050_SUSPEND_MODE;
2819 obj->odr = BMC050_REGULAR_DR;
2820 obj->rept_xy = BMC050_REGULAR_REPXY;
2821 obj->rept_z = BMC050_REGULAR_REPZ;
2822
2823 res = bmm050api_set_functional_state(BMC050_SUSPEND_MODE);
2824 if (res)
2825 {
2826 return -EIO;
2827 }
2828
2829 return 0;
2830 }
2831 /*----------------------------------------------------------------------------*/
2832 //static int bmm050_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info)
2833 //{
2834 // strcpy(info->type, BMM050_DEV_NAME);
2835 // return 0;
2836 //}
2837
2838 /*----------------------------------------------------------------------------*/
2839 static int bmm050_m_enable(int en)
2840 {
2841 int value = en;
2842 printk("bmm050_m_enable++\n");
2843
2844 if(value == 1)
2845 {
2846 atomic_set(&m_flag, 1);
2847 atomic_set(&open_flag, 1);
2848 }
2849 else
2850 {
2851 atomic_set(&m_flag, 0);
2852 if(atomic_read(&o_flag) == 0)
2853 {
2854 atomic_set(&open_flag, 0);
2855 }
2856 }
2857 wake_up(&open_wq);
2858
2859 bmm050_SetPowerMode(this_client, (value == 1));
2860
2861 /* set the flag */
2862 mutex_lock(&uplink_event_flag_mutex);
2863 uplink_event_flag |= BMMDRV_ULEVT_FLAG_M_ACTIVE;
2864 mutex_unlock(&uplink_event_flag_mutex);
2865 /* wake up the wait queue */
2866 wake_up(&uplink_event_flag_wq);
2867 printk("bmm050_m_enable--\n");
2868 return 0;
2869 }
2870
2871 static int bmm050_m_set_delay(u64 ns)
2872 {
2873 int value=0;
2874 printk("bmm050_m_set_delay++\n");
2875 value = (int)ns/1000/1000;
2876 if(value <= 20)
2877 {
2878 bmm050d_delay = 20;
2879 }
2880 else
2881 {
2882 bmm050d_delay = value;
2883 }
2884 /* set the flag */
2885 mutex_lock(&uplink_event_flag_mutex);
2886 uplink_event_flag |= BMMDRV_ULEVT_FLAG_M_DELAY;
2887 mutex_unlock(&uplink_event_flag_mutex);
2888 /* wake up the wait queue */
2889 wake_up(&uplink_event_flag_wq);
2890 printk("bmm050_m_set_delay--\n");
2891 return 0;
2892 }
2893 static int bmm050_m_open_report_data(int open)
2894 {
2895 return 0;
2896 }
2897
2898 static int bmm050_o_enable(int en)
2899 {
2900 int value =en;
2901 printk("bmm050_o_enable++\n");
2902 bmm050_m_enable(value);
2903 if(value == 1)
2904 {
2905 atomic_set(&o_flag, 1);
2906 atomic_set(&open_flag, 1);
2907 }
2908 else
2909 {
2910 atomic_set(&o_flag, 0);
2911 if(atomic_read(&m_flag) == 0)
2912 {
2913 atomic_set(&open_flag, 0);
2914 }
2915 }
2916 wake_up(&open_wq);
2917
2918 /* set the flag */
2919 mutex_lock(&uplink_event_flag_mutex);
2920 uplink_event_flag |= BMMDRV_ULEVT_FLAG_O_ACTIVE;
2921 mutex_unlock(&uplink_event_flag_mutex);
2922 /* wake up the wait queue */
2923 wake_up(&uplink_event_flag_wq);
2924 printk("bmm050_o_enable--\n");
2925 return 0;
2926 }
2927
2928 static int bmm050_o_set_delay(u64 ns)
2929 {
2930 int value=0;
2931 printk("bmm050_o_set_delay++\n");
2932 value = (int)ns/1000/1000;
2933 if(value <= 20)
2934 {
2935 bmm050d_delay = 20;
2936 }
2937 else
2938 {
2939 bmm050d_delay = value;
2940 }
2941 /* set the flag */
2942 mutex_lock(&uplink_event_flag_mutex);
2943 uplink_event_flag |= BMMDRV_ULEVT_FLAG_O_DELAY;
2944 mutex_unlock(&uplink_event_flag_mutex);
2945 /* wake up the wait queue */
2946 wake_up(&uplink_event_flag_wq);
2947 printk("bmm050_o_set_delay--\n");
2948 return 0;
2949
2950 }
2951 static int bmm050_o_open_report_data(int open)
2952 {
2953 return 0;
2954 }
2955
2956 static int bmm050_o_get_data(int* x ,int* y,int* z, int* status)
2957 {
2958 mutex_lock(&sensor_data_mutex);
2959
2960 *x = sensor_data[8];
2961 *y = sensor_data[9];
2962 *z = sensor_data[10];
2963 *status = sensor_data[11];
2964
2965 mutex_unlock(&sensor_data_mutex);
2966 return 0;
2967 }
2968
2969 static int bmm050_m_get_data(int* x ,int* y,int* z, int* status)
2970 {
2971 mutex_lock(&sensor_data_mutex);
2972
2973 *x = sensor_data[4];
2974 *y = sensor_data[5];
2975 *z = sensor_data[6];
2976 *status = sensor_data[7];
2977
2978 mutex_unlock(&sensor_data_mutex);
2979 return 0;
2980 }
2981
2982
2983 /*----------------------------------------------------------------------------*/
2984 static int bmm050_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
2985 {
2986 struct i2c_client *new_client;
2987 struct bmm050_i2c_data *data;
2988 int err = 0;
2989 struct mag_control_path ctl={0};
2990 struct mag_data_path mag_data={0};
2991
2992 if(!(data = kmalloc(sizeof(struct bmm050_i2c_data), GFP_KERNEL)))
2993 {
2994 err = -ENOMEM;
2995 goto exit;
2996 }
2997 memset(data, 0, sizeof(struct bmm050_i2c_data));
2998
2999 data->hw = get_cust_mag_hw();
3000 if((err = hwmsen_get_convert(data->hw->direction, &data->cvt)))
3001 {
3002 MSE_ERR("invalid direction: %d\n", data->hw->direction);
3003 goto exit;
3004 }
3005 atomic_set(&data->layout, data->hw->direction);
3006 atomic_set(&data->trace, 0);
3007
3008 mutex_init(&sensor_data_mutex);
3009 mutex_init(&uplink_event_flag_mutex);
3010
3011 init_waitqueue_head(&open_wq);
3012 init_waitqueue_head(&uplink_event_flag_wq);
3013
3014 data->client = client;
3015 new_client = data->client;
3016 i2c_set_clientdata(new_client, data);
3017
3018 this_client = new_client;
3019
3020 //initial client
3021 if ((err = bmm050_init_client(this_client)))
3022 {
3023 MSE_ERR("fail to initialize client");
3024 goto exit_client_failed;
3025 }
3026
3027 /* Register sysfs attribute */
3028 if((err = bmm050_create_attr(&(bmm050_init_info.platform_diver_addr->driver))))
3029 {
3030 MSE_ERR("create attribute err = %d\n", err);
3031 goto exit_sysfs_create_group_failed;
3032 }
3033
3034 if((err = misc_register(&bmm050_device)))
3035 {
3036 MSE_ERR("bmm050_device register failed\n");
3037 goto exit_misc_device_register_failed;
3038 }
3039
3040 ctl.m_enable = bmm050_m_enable;
3041 ctl.m_set_delay = bmm050_m_set_delay;
3042 ctl.m_open_report_data = bmm050_m_open_report_data;
3043 ctl.o_enable = bmm050_o_enable;
3044 ctl.o_set_delay = bmm050_o_set_delay;
3045 ctl.o_open_report_data = bmm050_o_open_report_data;
3046 ctl.is_report_input_direct = false;
3047
3048 err = mag_register_control_path(&ctl);
3049 if(err)
3050 {
3051 MAG_ERR("register mag control path err\n");
3052 goto exit_kfree;
3053 }
3054
3055 mag_data.div_m = CONVERT_M_DIV;
3056 mag_data.div_o = CONVERT_O_DIV;
3057 mag_data.get_data_o = bmm050_o_get_data;
3058 mag_data.get_data_m = bmm050_m_get_data;
3059
3060 err = mag_register_data_path(&mag_data);
3061 if(err)
3062 {
3063 MAG_ERR("register data control path err\n");
3064 goto exit_kfree;
3065 }
3066
3067 #if CONFIG_HAS_EARLYSUSPEND
3068 data->early_drv.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING - 2,
3069 data->early_drv.suspend = bmm050_early_suspend,
3070 data->early_drv.resume = bmm050_late_resume,
3071 register_early_suspend(&data->early_drv);
3072 #endif
3073
3074 bmm050_init_flag =1;
3075 MSE_LOG("%s: OK\n", __func__);
3076 return 0;
3077
3078 exit_client_failed:
3079 exit_sysfs_create_group_failed:
3080 exit_misc_device_register_failed:
3081 exit_kfree:
3082 kfree(data);
3083 exit:
3084 MSE_ERR( "%s: err = %d\n", __func__, err);
3085 return err;
3086 }
3087 /*----------------------------------------------------------------------------*/
3088 static int bmm050_i2c_remove(struct i2c_client *client)
3089 {
3090 struct bmm050_i2c_data *obj = i2c_get_clientdata(client);
3091
3092 if(bmm050_delete_attr(&(bmm050_init_info.platform_diver_addr->driver)))
3093 {
3094 MSE_ERR( "bmm050_delete_attr fail");
3095 }
3096
3097 #ifdef CONFIG_HAS_EARLYSUSPEND
3098 unregister_early_suspend(&obj->early_drv);
3099 #endif
3100 bmm050api_set_functional_state(BMC050_SUSPEND_MODE);
3101 this_client = NULL;
3102 i2c_unregister_device(client);
3103 kfree(obj);
3104 misc_deregister(&bmm050_device);
3105 return 0;
3106 }
3107 /*----------------------------------------------------------------------------*/
3108 static struct i2c_driver bmm050_i2c_driver = {
3109 .driver = {
3110 // .owner = THIS_MODULE,
3111 .name = BMM050_DEV_NAME,
3112 },
3113 .probe = bmm050_i2c_probe,
3114 .remove = bmm050_i2c_remove,
3115 // .detect = bmm050_i2c_detect,
3116 #if !defined(CONFIG_HAS_EARLYSUSPEND)
3117 .suspend = bmm050_suspend,
3118 .resume = bmm050_resume,
3119 #endif
3120 .id_table = bmm050_i2c_id,
3121 // .address_data = &bmm050_addr_data,
3122 };
3123 /*----------------------------------------------------------------------------*/
3124 /*----------------------------------------------------------------------------*/
3125 static int bmm050_remove(void)
3126 {
3127 struct mag_hw *hw = get_cust_mag_hw();
3128
3129 i2c_del_driver(&bmm050_i2c_driver);
3130 bmm050_power(hw, 0);
3131 return 0;
3132 }
3133 /*----------------------------------------------------------------------------*/
3134 static int bmm050_local_init(void)
3135 {
3136 struct mag_hw *hw = get_cust_mag_hw();
3137 //printk("fwq loccal init+++\n");
3138
3139 bmm050_power(hw, 1);
3140 if(i2c_add_driver(&bmm050_i2c_driver))
3141 {
3142 MSE_ERR("add driver error\n");
3143 return -1;
3144 }
3145 if(-1 == bmm050_init_flag)
3146 {
3147 return -1;
3148 }
3149 //printk("fwq loccal init---\n");
3150 return 0;
3151 }
3152
3153 static int __init bmm050_init(void)
3154 {
3155 struct mag_hw *hw = get_cust_mag_hw();
3156 MSE_LOG("%s: i2c_number=%d\n", __func__,hw->i2c_num);
3157 i2c_register_board_info(hw->i2c_num, &i2c_bmm050, 1);
3158 mag_driver_add(&bmm050_init_info);
3159 return 0;
3160 }
3161 /*----------------------------------------------------------------------------*/
3162 static void __exit bmm050_exit(void)
3163 {
3164 MSE_FUN();
3165 }
3166 /*----------------------------------------------------------------------------*/
3167 module_init(bmm050_init);
3168 module_exit(bmm050_exit);
3169
3170 MODULE_AUTHOR("hongji.zhou@bosch-sensortec.com");
3171 MODULE_DESCRIPTION("bmm050 compass driver");
3172 MODULE_LICENSE("GPL");
3173