1 /* bmm050.c - bmm050 compass driver
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
7 * (C) Copyright 2011 Bosch Sensortec GmbH
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>
29 #include <mach/mt_typedefs.h>
30 #include <mach/mt_gpio.h>
31 #include <mach/mt_pm_ldo.h>
34 #define POWER_NONE_MACRO MT65XX_POWER_NONE
37 #include <linux/hwmsen_helper.h>
38 #include <linux/hwmsensor.h>
39 #include <linux/hwmsen_dev.h>
40 #include <linux/sensors_io.h>
44 /*----------------------------------------------------------------------------*/
45 /* BMM050 API Section */
46 /*----------------------------------------------------------------------------*/
47 #define BMC050_U16 unsigned short
48 #define BMC050_S16 signed short
49 #define BMC050_S32 signed int
51 #define BMC050_BUS_WR_RETURN_TYPE char
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)
60 #define BMC050_BUS_WRITE_FUNC(device_addr, register_addr, register_data, wr_len) bus_write(device_addr, register_addr, register_data, wr_len)
62 #define BMC050_BUS_RD_RETURN_TYPE char
65 //#define BMC050_BUS_RD_PARAM_TYPES\
66 // unsigned char, unsigned char, unsigned char *, unsigned char
68 //#define BMC050_BUS_RD_PARAM_ORDER (device_addr, register_addr, register_data)
71 #define BMC050_BUS_READ_FUNC(device_addr, register_addr, register_data, rd_len) bus_read(device_addr, register_addr, register_data, rd_len)
73 #define BMC050_DELAY_RETURN_TYPE void
75 #define BMC050_DELAY_PARAM_TYPES unsigned int
78 //#define BMC050_DELAY_FUNC(delay_in_msec)
79 //delay_func(delay_in_msec)
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
93 #define BMC050_RETURN_FUNCTION_TYPE char
94 #define BMC050_I2C_ADDRESS 0x10
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
103 /* Fixed Data Registers */
104 #define BMC050_CHIP_ID 0x40
105 #define BMC050_REVISION_ID 0x41
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
117 /* Status Registers */
118 #define BMC050_INT_STAT 0x4A
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
365 #define BMC050_X_AXIS 0
366 #define BMC050_Y_AXIS 1
367 #define BMC050_Z_AXIS 2
368 #define BMC050_RESISTANCE 3
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
387 #define BMC050_NORMAL_MODE 0x00
388 #define BMC050_FORCED_MODE 0x01
389 #define BMC050_SUSPEND_MODE 0x02
390 #define BMC050_SLEEP_MODE 0x03
392 #define BMC050_ADVANCED_SELFTEST_OFF 0
393 #define BMC050_ADVANCED_SELFTEST_NEGATIVE 2
394 #define BMC050_ADVANCED_SELFTEST_POSITIVE 3
396 #define BMC050_NEGATIVE_SATURATION_Z -32767
397 #define BMC050_POSITIVE_SATURATION_Z 32767
399 #define BMC050_SPI_RD_MASK 0x80
400 #define BMC050_READ_SET 0x01
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
407 #define BMC050_WR_FUNC_PTR\
408 char (*bus_write)(unsigned char, unsigned char,\
409 unsigned char *, unsigned char)
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
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
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
435 /* Conversion factors*/
436 #define BMC050_CONVFACTOR_LSB_UT 6
439 #define BMC050_GET_BITSLICE(regvar, bitname)\
440 ((regvar & bitname##__MSK) >> bitname##__POS)
443 #define BMC050_SET_BITSLICE(regvar, bitname, val)\
444 ((regvar & ~bitname##__MSK) | ((val<<bitname##__POS)&bitname##__MSK))
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
454 #define BMC050_PRESETMODE_LOWPOWER 1
455 #define BMC050_PRESETMODE_REGULAR 2
456 #define BMC050_PRESETMODE_HIGHACCURACY 3
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
463 /* PRESET MODES - REPETITIONS-XY RATES */
464 #define BMC050_LOWPOWER_REPXY 2
465 #define BMC050_REGULAR_REPXY 5
466 #define BMC050_HIGHACCURACY_REPXY 40
468 /* PRESET MODES - REPETITIONS-Z RATES */
469 #define BMC050_LOWPOWER_REPZ 4
470 #define BMC050_REGULAR_REPZ 13
471 #define BMC050_HIGHACCURACY_REPZ 89
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
484 /*user defined Structures*/
485 struct bmm050api_mdata
{
489 BMC050_U16 resistance
;
492 struct bmm050api_offset
{
499 unsigned char company_id
;
500 unsigned char revision_info
;
501 unsigned char dev_addr
;
505 void(*delay_msec
)(BMC050_MDELAY_DATA_TYPE
);
518 unsigned char dig_xy1
;
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(
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(
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
);
677 BMC050_RETURN_FUNCTION_TYPE
bmm050api_set_presetmode(unsigned char mode
);
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);
684 static int bmm050_init_flag
=-1; // 0<==>OK -1 <==> fail
686 static struct mag_init_info bmm050_init_info
= {
688 .init
= bmm050_local_init
,
689 .uninit
= bmm050_remove
,
695 BMC050_RETURN_FUNCTION_TYPE
bmm050api_init(struct bmc050
*bmc050
)
697 BMC050_RETURN_FUNCTION_TYPE comres
= 0;
698 unsigned char a_data_u8r
[2];
701 p_bmc050
->dev_addr
= BMC050_I2C_ADDRESS
;
703 /* set device from suspend into sleep mode */
704 bmm050api_set_powermode(BMC050_ON
);
706 /* wait two millisecond for bmc to settle */
707 p_bmc050
->delay_msec(BMC050_DELAY_SETTLING_TIME
);
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];
715 /* Function to initialise trim values */
716 bmm050api_init_trim_registers();
720 BMC050_RETURN_FUNCTION_TYPE
bmm050api_init_trim_registers(void)
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);
737 /* shorts can not be recasted into (unsigned char*)
738 * due to possible mixup between trim data
739 * arrangement and memory arrangement */
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)
745 SHIFT_LEFT_8_POSITION
) | a_data_u8r
[0]);
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]);
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]);
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]);
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]);
775 BMC050_RETURN_FUNCTION_TYPE
bmm050api_get_datarate(unsigned char *data_rate
)
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
;
782 comres
= p_bmc050
->BMC050_BUS_READ_FUNC(
786 *data_rate
= BMC050_GET_BITSLICE(v_data_u8r
,
793 BMC050_RETURN_FUNCTION_TYPE
bmm050api_set_datarate(unsigned char data_rate
)
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
;
800 comres
= p_bmc050
->BMC050_BUS_READ_FUNC(
804 v_data1_u8r
= BMC050_SET_BITSLICE(v_data1_u8r
,
805 BMC050_CNTL_DR
, data_rate
);
806 comres
|= p_bmc050
->BMC050_BUS_WRITE_FUNC(
815 BMC050_RETURN_FUNCTION_TYPE
bmm050api_get_powermode(unsigned char *mode
)
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
;
822 comres
= p_bmc050
->BMC050_BUS_READ_FUNC(
824 BMC050_POWER_CNTL_PCB__REG
,
826 *mode
= BMC050_GET_BITSLICE(v_data_u8r
,
827 BMC050_POWER_CNTL_PCB
);
832 BMC050_RETURN_FUNCTION_TYPE
bmm050api_set_powermode(unsigned char mode
)
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
;
839 comres
= p_bmc050
->BMC050_BUS_READ_FUNC(
841 BMC050_POWER_CNTL_PCB__REG
,
843 v_data_u8r
= BMC050_SET_BITSLICE(v_data_u8r
,
844 BMC050_POWER_CNTL_PCB
, mode
);
845 comres
|= p_bmc050
->BMC050_BUS_WRITE_FUNC(
847 BMC050_POWER_CNTL_PCB__REG
,
853 BMC050_RETURN_FUNCTION_TYPE
bmm050api_get_functional_state(
854 unsigned char *functional_state
)
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
;
861 comres
= p_bmc050
->BMC050_BUS_READ_FUNC(
863 BMC050_CNTL_OPMODE__REG
,
865 *functional_state
= BMC050_GET_BITSLICE(
866 v_data_u8r
, BMC050_CNTL_OPMODE
);
872 BMC050_RETURN_FUNCTION_TYPE
bmm050api_set_functional_state(
873 unsigned char functional_state
)
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
;
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
);
889 comres
|= p_bmc050
->BMC050_BUS_READ_FUNC(
891 BMC050_CNTL_OPMODE__REG
,
893 v_data1_u8r
= BMC050_SET_BITSLICE(
897 comres
|= p_bmc050
->BMC050_BUS_WRITE_FUNC(
899 BMC050_CNTL_OPMODE__REG
,
903 case BMC050_SUSPEND_MODE
:
904 comres
= bmm050api_set_powermode(BMC050_OFF
);
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
);
913 comres
|= p_bmc050
->BMC050_BUS_READ_FUNC(
915 BMC050_CNTL_OPMODE__REG
,
917 v_data1_u8r
= BMC050_SET_BITSLICE(
919 BMC050_CNTL_OPMODE
, BMC050_ON
);
920 comres
|= p_bmc050
->BMC050_BUS_WRITE_FUNC(
922 BMC050_CNTL_OPMODE__REG
,
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
);
932 comres
|= p_bmc050
->BMC050_BUS_READ_FUNC(
934 BMC050_CNTL_OPMODE__REG
,
936 v_data1_u8r
= BMC050_SET_BITSLICE(
940 comres
|= p_bmc050
->BMC050_BUS_WRITE_FUNC(
942 BMC050_CNTL_OPMODE__REG
,
946 comres
= E_BMC050_OUT_OF_RANGE
;
953 BMC050_RETURN_FUNCTION_TYPE
bmm050api_get_repetitions_XY(
954 unsigned char *no_repetitions_xy
)
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
;
961 comres
= p_bmc050
->BMC050_BUS_READ_FUNC(
963 BMC050_NO_REPETITIONS_XY
,
965 *no_repetitions_xy
= v_data_u8r
;
970 BMC050_RETURN_FUNCTION_TYPE
bmm050api_set_repetitions_XY(
971 unsigned char no_repetitions_xy
)
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
;
978 v_data_u8r
= no_repetitions_xy
;
979 comres
= p_bmc050
->BMC050_BUS_WRITE_FUNC(
981 BMC050_NO_REPETITIONS_XY
,
987 BMC050_RETURN_FUNCTION_TYPE
bmm050api_get_repetitions_Z(
988 unsigned char *no_repetitions_z
)
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
;
995 comres
= p_bmc050
->BMC050_BUS_READ_FUNC(
997 BMC050_NO_REPETITIONS_Z
,
999 *no_repetitions_z
= v_data_u8r
;
1004 BMC050_RETURN_FUNCTION_TYPE
bmm050api_set_repetitions_Z(
1005 unsigned char no_repetitions_z
)
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
;
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);
1020 BMC050_RETURN_FUNCTION_TYPE
bmm050api_get_raw_xyz(struct bmm050api_mdata
*mdata
)
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
;
1027 comres
= p_bmc050
->BMC050_BUS_READ_FUNC(p_bmc050
->dev_addr
,
1028 BMC050_DATAX_LSB
, a_data_u8r
, 6);
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
)
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
)
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
)
1055 BMC050_RETURN_FUNCTION_TYPE
bmm050api_read_mdataXYZ(struct bmm050api_mdata
*mdata
)
1057 BMC050_RETURN_FUNCTION_TYPE comres
;
1059 unsigned char a_data_u8r
[8];
1062 BMC050_S16 raw_dataX
;
1063 BMC050_S16 raw_dataY
;
1064 BMC050_S16 raw_dataZ
;
1065 BMC050_U16 raw_dataR
;
1068 if (p_bmc050
== BMC050_NULL
) {
1069 comres
= E_BMC050_NULL_PTR
;
1071 comres
= p_bmc050
->BMC050_BUS_READ_FUNC(p_bmc050
->dev_addr
,
1072 BMC050_DATAX_LSB
, a_data_u8r
, 8);
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]);
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]);
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]);
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
)
1100 SHIFT_LEFT_6_POSITION
) | a_data_u8r
[6]);
1102 /* Compensation for X axis */
1103 mdata
->datax
= bmm050api_compensate_X(raw_dataXYZ
.raw_dataX
,
1104 raw_dataXYZ
.raw_dataR
);
1106 /* Compensation for Y axis */
1107 mdata
->datay
= bmm050api_compensate_Y(raw_dataXYZ
.raw_dataY
,
1108 raw_dataXYZ
.raw_dataR
);
1110 /* Compensation for Z axis */
1111 mdata
->dataz
= bmm050api_compensate_Z(raw_dataXYZ
.raw_dataZ
,
1112 raw_dataXYZ
.raw_dataR
);
1117 BMC050_S16
bmm050api_compensate_X(BMC050_S16 mdata_x
, BMC050_U16 data_R
)
1119 BMC050_S16 inter_retval
;
1120 if (mdata_x
!= BMC050_FLIP_OVERFLOW_ADCVAL
/* no overflow */
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
)
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);
1139 inter_retval
= BMC050_OVERFLOW_OUTPUT
;
1141 return inter_retval
;
1144 BMC050_S16
bmm050api_compensate_Y(BMC050_S16 mdata_y
, BMC050_U16 data_R
)
1146 BMC050_S16 inter_retval
;
1147 if (mdata_y
!= BMC050_FLIP_OVERFLOW_ADCVAL
/* no overflow */
1149 inter_retval
= ((BMC050_S16
)(((BMC050_U16
)(((
1150 (BMC050_S32
)p_bmc050
->dig_xyz1
) << 14) /
1152 data_R
: p_bmc050
->dig_xyz1
))) -
1153 ((BMC050_U16
)0x4000)));
1154 inter_retval
= ((BMC050_S16
)((((BMC050_S32
)mdata_y
) *
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))))
1166 (((BMC050_S16
)p_bmc050
->dig_y1
) << 3);
1169 inter_retval
= BMC050_OVERFLOW_OUTPUT
;
1171 return inter_retval
;
1174 BMC050_S16
bmm050api_compensate_Z(BMC050_S16 mdata_z
, BMC050_U16 data_R
)
1177 if ((mdata_z
!= BMC050_HALL_OVERFLOW_ADCVAL
) /* no overflow */
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
) -
1183 p_bmc050
->dig_xyz1
))))>>2)) /
1185 ((BMC050_S16
)(((((BMC050_S32
)
1187 ((((BMC050_S16
)data_R
) << 1)))+
1189 /* saturate result to +/- 2 mT */
1190 if (retval
> BMC050_POSITIVE_SATURATION_Z
) {
1191 retval
= BMC050_POSITIVE_SATURATION_Z
;
1193 if (retval
< BMC050_NEGATIVE_SATURATION_Z
)
1194 retval
= BMC050_NEGATIVE_SATURATION_Z
;
1198 retval
= BMC050_OVERFLOW_OUTPUT
;
1200 return (BMC050_S16
)retval
;
1203 BMC050_RETURN_FUNCTION_TYPE
bmm050api_soft_reset(void)
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
;
1210 v_data_u8r
= BMC050_ON
;
1212 comres
= p_bmc050
->BMC050_BUS_READ_FUNC(
1214 BMC050_POWER_CNTL_SRST7__REG
,
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(
1221 BMC050_POWER_CNTL_SRST7__REG
, &v_data_u8r
, 1);
1223 comres
|= p_bmc050
->BMC050_BUS_READ_FUNC(
1225 BMC050_POWER_CNTL_SRST1__REG
,
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(
1232 BMC050_POWER_CNTL_SRST1__REG
,
1235 p_bmc050
->delay_msec(BMC050_DELAY_SOFTRESET
);
1241 BMC050_RETURN_FUNCTION_TYPE
bmm050api_get_self_test_XYZ(
1242 unsigned char *self_testxyz
)
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
;
1249 comres
= p_bmc050
->BMC050_BUS_READ_FUNC(
1250 p_bmc050
->dev_addr
, BMC050_DATAX_LSB_TESTX__REG
,
1253 v_result_u8r
= BMC050_GET_BITSLICE(a_data_u8r
[4],
1254 BMC050_DATAZ_LSB_TESTZ
);
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
));
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
));
1264 *self_testxyz
= v_result_u8r
;
1269 BMC050_RETURN_FUNCTION_TYPE
bmm050api_set_selftest(unsigned char selftest
)
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
;
1276 comres
= p_bmc050
->BMC050_BUS_READ_FUNC(
1277 p_bmc050
->dev_addr
, BMC050_CNTL_S_TEST__REG
,
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
,
1288 BMC050_RETURN_FUNCTION_TYPE
bmm050api_perform_advanced_selftest(
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
;
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
);
1301 /* set normal accuracy mode */
1302 comres
|= bmm050api_set_repetitions_Z(BMC050_LOWPOWER_REPZ
);
1303 /* 14 repetitions Z in normal accuracy mode */
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
);
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);
1319 /* read result from positive field measurement */
1320 comres
|= bmm050api_read_mdataZ(&result_positive
);
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 */
1329 /* read result from negative field measurement */
1330 comres
|= bmm050api_read_mdataZ(&result_negative
);
1332 /* turn off self test current */
1333 comres
|= bmm050api_set_adv_selftest(
1334 BMC050_ADVANCED_SELFTEST_OFF
);
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
);
1342 /* write out difference in positive and negative field.
1343 * This should be ~ 200 mT = 3200 LSB */
1344 *diff_z
= (result_positive
- result_negative
);
1349 BMC050_RETURN_FUNCTION_TYPE
bmm050api_set_control_measurement_x(
1350 unsigned char enable_disable
)
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
;
1357 comres
= p_bmc050
->BMC050_BUS_READ_FUNC(
1359 BMC050_SENS_CNTL_CHANNELX__REG
,
1361 v_data1_u8r
= BMC050_SET_BITSLICE(v_data1_u8r
,
1362 BMC050_SENS_CNTL_CHANNELX
,
1364 comres
|= p_bmc050
->BMC050_BUS_WRITE_FUNC(
1366 BMC050_SENS_CNTL_CHANNELX__REG
,
1372 BMC050_RETURN_FUNCTION_TYPE
bmm050api_set_control_measurement_y(
1373 unsigned char enable_disable
)
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
;
1380 comres
= p_bmc050
->BMC050_BUS_READ_FUNC(
1382 BMC050_SENS_CNTL_CHANNELY__REG
,
1384 v_data1_u8r
= BMC050_SET_BITSLICE(
1386 BMC050_SENS_CNTL_CHANNELY
,
1388 comres
|= p_bmc050
->BMC050_BUS_WRITE_FUNC(
1390 BMC050_SENS_CNTL_CHANNELY__REG
,
1396 BMC050_RETURN_FUNCTION_TYPE
bmm050api_set_adv_selftest(unsigned char adv_selftest
)
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
;
1403 switch (adv_selftest
) {
1404 case BMC050_ADVANCED_SELFTEST_OFF
:
1405 comres
= p_bmc050
->BMC050_BUS_READ_FUNC(
1407 BMC050_CNTL_ADV_ST__REG
,
1409 v_data1_u8r
= BMC050_SET_BITSLICE(
1412 BMC050_ADVANCED_SELFTEST_OFF
);
1413 comres
|= p_bmc050
->BMC050_BUS_WRITE_FUNC(
1415 BMC050_CNTL_ADV_ST__REG
,
1418 case BMC050_ADVANCED_SELFTEST_POSITIVE
:
1419 comres
= p_bmc050
->BMC050_BUS_READ_FUNC(
1421 BMC050_CNTL_ADV_ST__REG
,
1423 v_data1_u8r
= BMC050_SET_BITSLICE(
1426 BMC050_ADVANCED_SELFTEST_POSITIVE
);
1427 comres
|= p_bmc050
->BMC050_BUS_WRITE_FUNC(
1429 BMC050_CNTL_ADV_ST__REG
,
1432 case BMC050_ADVANCED_SELFTEST_NEGATIVE
:
1433 comres
= p_bmc050
->BMC050_BUS_READ_FUNC(
1435 BMC050_CNTL_ADV_ST__REG
,
1437 v_data1_u8r
= BMC050_SET_BITSLICE(
1440 BMC050_ADVANCED_SELFTEST_NEGATIVE
);
1441 comres
|= p_bmc050
->BMC050_BUS_WRITE_FUNC(
1443 BMC050_CNTL_ADV_ST__REG
,
1453 BMC050_RETURN_FUNCTION_TYPE
bmm050api_read_mdataZ(BMC050_S16
*mdata_z
)
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
;
1461 comres
= bmm050api_get_halldataZ(&raw_dataZ
);
1462 comres
|= bmm050api_get_mdataResistance(&raw_dataR
);
1464 /* Compensation for Z axis */
1465 *mdata_z
= bmm050api_compensate_Z(raw_dataZ
, raw_dataR
);
1470 BMC050_RETURN_FUNCTION_TYPE
bmm050api_get_halldataZ(BMC050_S16
*mdata_z
)
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
;
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
)
1489 BMC050_RETURN_FUNCTION_TYPE
bmm050api_get_mdataResistance(
1490 BMC050_U16
*mdata_resistance
)
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
;
1497 comres
= p_bmc050
->BMC050_BUS_READ_FUNC(
1499 BMC050_R_LSB_VALUE__REG
,
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
)
1511 /*----------------------------------------------------------------------------*/
1512 /* End of API Section */
1513 /*----------------------------------------------------------------------------*/
1515 /*----------------------------------------------------------------------------*/
1517 #define BMM050_DEV_NAME "bmm050"
1518 /*----------------------------------------------------------------------------*/
1520 #define SENSOR_CHIP_ID_BMM (0x32)
1522 #define BMM050_DEFAULT_DELAY 100
1523 #define BMM050_BUFSIZE 0x20
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)
1530 static struct i2c_client
*this_client
= NULL
;
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
);
1538 static int bmm050d_delay
= BMM050_DEFAULT_DELAY
;
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);
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 */
1550 BMMDRV_ULEVT_FLAG_O_ACTIVE
= 0x01,
1551 BMMDRV_ULEVT_FLAG_M_ACTIVE
= 0x02,
1553 BMMDRV_ULEVT_FLAG_O_DELAY
= 0x04,
1554 BMMDRV_ULEVT_FLAG_M_DELAY
= 0x08,
1557 BMMDRV_ULEVT_FLAG_ALL
= 0xff
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))};
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 /*----------------------------------------------------------------------------*/
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,
1579 /*----------------------------------------------------------------------------*/
1580 struct bmm050_i2c_data
{
1581 struct i2c_client
*client
;
1585 struct hwmsen_convert cvt
;
1587 struct bmc050 device
;
1594 #if defined(CONFIG_HAS_EARLYSUSPEND)
1595 struct early_suspend early_drv
;
1599 /*----------------------------------------------------------------------------*/
1600 static void bmm050_power(struct mag_hw
*hw
, unsigned int on
)
1602 static unsigned int power_on
= 0;
1604 if(hw
->power_id
!= POWER_NONE_MACRO
)
1606 MSE_LOG("power %s\n", on
? "on" : "off");
1609 MSE_LOG("ignore power control: %d\n", on
);
1613 if(!hwPowerOn(hw
->power_id
, hw
->power_vol
, "bmm050"))
1615 MSE_ERR( "power on fails!!\n");
1620 if(!hwPowerDown(hw
->power_id
, "bmm050"))
1622 MSE_ERR( "power off fail!!\n");
1629 // Daemon application save the data
1630 static int ECS_SaveData(int buf
[CALIBRATION_DATA_SIZE
])
1633 struct bmm050_i2c_data
*data
= i2c_get_clientdata(this_client
);
1636 mutex_lock(&sensor_data_mutex
);
1639 case 2: /* SENSOR_HANDLE_MAGNETIC_FIELD */
1640 memcpy(sensor_data
+4, buf
+1, 4*sizeof(int));
1642 case 3: /* SENSOR_HANDLE_ORIENTATION */
1643 memcpy(sensor_data
+8, buf
+1, 4*sizeof(int));
1648 mutex_unlock(&sensor_data_mutex
);
1651 if(atomic_read(&data
->trace
) & MMC_HWM_DEBUG
)
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]);
1662 /*----------------------------------------------------------------------------*/
1663 static int ECS_GetRawData(int data
[3])
1665 struct bmm050api_mdata mdata
;
1666 struct bmm050_i2c_data
*obj
= i2c_get_clientdata(this_client
);
1667 u8 databuf
[2] = {BMC050_CONTROL
, 0x02};
1669 bmm050api_read_mdataXYZ(&mdata
);
1671 data
[0] = mdata
.datax
/16;
1672 data
[1] = mdata
.datay
/16;
1673 data
[2] = mdata
.dataz
/16;
1675 /* measure magnetic field for next sample */
1676 if (obj
->op_mode
== BMC050_SUSPEND_MODE
)
1678 /* power on firstly */
1679 bmm050api_set_powermode(BMC050_ON
);
1681 /* special treat of forced mode
1682 * for optimization */
1683 i2c_master_send(this_client
, databuf
, 2);
1684 obj
->op_mode
= BMC050_SLEEP_MODE
;
1688 /*----------------------------------------------------------------------------*/
1690 static int ECS_GetOpenStatus(void)
1692 wait_event_interruptible(open_wq, (atomic_read(&open_flag) != 0));
1693 return atomic_read(&open_flag);
1696 /*----------------------------------------------------------------------------*/
1697 static int bmm050_ReadChipInfo(char *buf
, int bufsize
)
1699 if((!buf
)||(bufsize
<= BMM050_BUFSIZE
-1))
1709 sprintf(buf
, "bmm050 Chip");
1712 /*----------------------------------------------------------------------------*/
1713 static void bmm050_SetPowerMode(struct i2c_client
*client
, bool enable
)
1715 struct bmm050_i2c_data
*obj
= i2c_get_clientdata(client
);
1718 if (enable
== FALSE
)
1720 if (bmm050api_set_functional_state(BMC050_SUSPEND_MODE
) != 0)
1722 MSE_ERR("fail to suspend sensor");
1728 if (obj
->op_mode
== BMC050_SUSPEND_MODE
)
1730 obj
->op_mode
= BMC050_SLEEP_MODE
;
1732 bmm050_restore_hw_cfg(client
);
1736 /*----------------------------------------------------------------------------*/
1737 /* Driver Attributes Functions Section */
1738 static ssize_t
show_daemon_name(struct device_driver
*ddri
, char *buf
)
1741 sprintf(strbuf
, "bmm050d");
1742 return sprintf(buf
, "%s", strbuf
);
1745 /*----------------------------------------------------------------------------*/
1746 static ssize_t
show_chipinfo_value(struct device_driver
*ddri
, char *buf
)
1748 char strbuf
[BMM050_BUFSIZE
];
1749 bmm050_ReadChipInfo(strbuf
, BMM050_BUFSIZE
);
1750 return sprintf(buf
, "%s\n", strbuf
);
1752 /*----------------------------------------------------------------------------*/
1753 static ssize_t
show_sensordata_value(struct device_driver
*ddri
, char *buf
)
1756 char strbuf
[BMM050_BUFSIZE
];
1758 ECS_GetRawData(sensordata
);
1759 sprintf(strbuf
, "%d %d %d\n", sensordata
[0],sensordata
[1],sensordata
[2]);
1760 return sprintf(buf
, "%s\n", strbuf
);
1762 /*----------------------------------------------------------------------------*/
1763 static ssize_t
show_posturedata_value(struct device_driver
*ddri
, char *buf
)
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]);
1772 return sprintf(buf
, "%s\n", strbuf
);;
1775 /*----------------------------------------------------------------------------*/
1776 static ssize_t
show_layout_value(struct device_driver
*ddri
, char *buf
)
1778 struct bmm050_i2c_data
*data
= i2c_get_clientdata(this_client
);
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]);
1784 /*----------------------------------------------------------------------------*/
1785 static ssize_t
store_layout_value(struct device_driver
*ddri
, const char *buf
, size_t count
)
1787 struct i2c_client
*client
= this_client
;
1788 struct bmm050_i2c_data
*data
= i2c_get_clientdata(client
);
1791 if(1 == sscanf(buf
, "%d", &layout
))
1793 atomic_set(&data
->layout
, layout
);
1794 if(!hwmsen_get_convert(layout
, &data
->cvt
))
1796 MSE_ERR( "HWMSEN_GET_CONVERT function error!\r\n");
1798 else if(!hwmsen_get_convert(data
->hw
->direction
, &data
->cvt
))
1800 MSE_ERR( "invalid layout: %d, restore to %d\n", layout
, data
->hw
->direction
);
1804 MSE_ERR( "invalid layout: (%d, %d)\n", layout
, data
->hw
->direction
);
1805 hwmsen_get_convert(0, &data
->cvt
);
1810 MSE_ERR( "invalid format = '%s'\n", buf
);
1815 /*----------------------------------------------------------------------------*/
1816 static ssize_t
show_status_value(struct device_driver
*ddri
, char *buf
)
1818 struct bmm050_i2c_data
*data
= i2c_get_clientdata(this_client
);
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
);
1828 len
+= snprintf(buf
+len
, PAGE_SIZE
-len
, "CUST: NULL\n");
1833 /*----------------------------------------------------------------------------*/
1834 static ssize_t
show_trace_value(struct device_driver
*ddri
, char *buf
)
1837 struct bmm050_i2c_data
*obj
= i2c_get_clientdata(this_client
);
1840 MSE_ERR( "bmm050_i2c_data is null!!\n");
1844 res
= snprintf(buf
, PAGE_SIZE
, "0x%04X\n", atomic_read(&obj
->trace
));
1847 /*----------------------------------------------------------------------------*/
1848 static ssize_t
store_trace_value(struct device_driver
*ddri
, const char *buf
, size_t count
)
1850 struct bmm050_i2c_data
*obj
= i2c_get_clientdata(this_client
);
1854 MSE_ERR( "bmm050_i2c_data is null!!\n");
1858 if(1 == sscanf(buf
, "0x%x", &trace
))
1860 atomic_set(&obj
->trace
, trace
);
1864 MSE_ERR( "invalid content: '%s', length = %d\n", buf
, count
);
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
)
1875 struct bmm050_i2c_data
*obj
= i2c_get_clientdata(this_client
);
1876 struct bmm050api_mdata mdata
;
1879 bmm050api_read_mdataXYZ(&mdata
);
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
;
1886 return sprintf(buf
, "%hd %hd %hd\n", mag
[BMM050_AXIS_X
], mag
[BMM050_AXIS_Y
], mag
[BMM050_AXIS_Z
]);
1888 /*----------------------------------------------------------------------------*/
1889 static ssize_t
show_cpsopmode_value(struct device_driver
*ddri
, char *buf
)
1891 //struct bmm050_i2c_data *obj = i2c_get_clientdata(this_client);
1895 bmm050api_get_powermode(&power_mode
);
1898 bmm050api_get_functional_state(&op_mode
);
1902 op_mode
= BMC050_SUSPEND_MODE
;
1905 MSE_LOG("op_mode: %d", op_mode
);
1907 return sprintf(buf
, "%d\n", op_mode
);
1910 /*----------------------------------------------------------------------------*/
1911 static ssize_t
store_cpsopmode_value(struct device_driver
*ddri
, const char *buf
, size_t count
)
1913 struct bmm050_i2c_data
*obj
= i2c_get_clientdata(this_client
);
1917 err
= strict_strtoul(buf
, 10, &op_mode
);
1919 if (((unsigned char)op_mode > 3) || (op_mode == obj->op_mode))
1923 if((unsigned char)op_mode
> 3)
1927 if(op_mode
== obj
->op_mode
)
1933 if (BMC050_FORCED_MODE
== op_mode
)
1935 u8 databuf
[2] = {BMC050_CONTROL
, 0x02};
1937 if (obj
->op_mode
== BMC050_SUSPEND_MODE
)
1939 /* power on firstly */
1940 bmm050api_set_powermode(BMC050_ON
);
1942 /* special treat of forced mode
1943 * for optimization */
1944 i2c_master_send(this_client
, databuf
, 2);
1945 obj
->op_mode
= BMC050_SLEEP_MODE
;
1949 bmm050api_set_functional_state((unsigned char)op_mode
);
1950 obj
->op_mode
= op_mode
;
1955 /*----------------------------------------------------------------------------*/
1956 static ssize_t
show_cpsreptxy_value(struct device_driver
*ddri
, char *buf
)
1958 unsigned char data
= 0;
1962 bmm050api_get_powermode(&power_mode
);
1965 err
= bmm050api_get_repetitions_XY(&data
);
1975 return sprintf(buf
, "%d\n", data
);
1977 /*----------------------------------------------------------------------------*/
1978 static ssize_t
store_cpsreptxy_value(struct device_driver
*ddri
, const char *buf
, size_t count
)
1980 struct bmm050_i2c_data
*obj
= i2c_get_clientdata(this_client
);
1981 unsigned long tmp
= 0;
1986 err
= strict_strtoul(buf
, 10, &tmp
);
1993 data
= (unsigned char)tmp
;
1995 bmm050api_get_powermode(&power_mode
);
1998 err
= bmm050api_set_repetitions_XY(data
);
2001 //mdelay(BMM_I2C_WRITE_DELAY_TIME);
2002 obj
->rept_xy
= data
;
2015 /*----------------------------------------------------------------------------*/
2016 static ssize_t
show_cpsreptz_value(struct device_driver
*ddri
, char *buf
)
2018 unsigned char data
= 0;
2022 bmm050api_get_powermode(&power_mode
);
2025 err
= bmm050api_get_repetitions_Z(&data
);
2035 return sprintf(buf
, "%d\n", data
);
2037 /*----------------------------------------------------------------------------*/
2038 static ssize_t
store_cpsreptz_value(struct device_driver
*ddri
, const char *buf
, size_t count
)
2040 struct bmm050_i2c_data
*obj
= i2c_get_clientdata(this_client
);
2041 unsigned long tmp
= 0;
2046 err
= strict_strtoul(buf
, 10, &tmp
);
2053 data
= (unsigned char)tmp
;
2055 bmm050api_get_powermode(&power_mode
);
2058 err
= bmm050api_set_repetitions_Z(data
);
2061 //mdelay(BMM_I2C_WRITE_DELAY_TIME);
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
,
2096 &driver_attr_cpsdata
,
2097 &driver_attr_cpsopmode
,
2098 &driver_attr_cpsreptxy
,
2099 &driver_attr_cpsreptz
,
2101 /*----------------------------------------------------------------------------*/
2102 static int bmm050_create_attr(struct device_driver
*driver
)
2105 int num
= (int)(sizeof(bmm050_attr_list
)/sizeof(bmm050_attr_list
[0]));
2111 for(idx
= 0; idx
< num
; idx
++)
2113 if((err
= driver_create_file(driver
, bmm050_attr_list
[idx
])))
2115 MSE_ERR( "driver_create_file (%s) = %d\n", bmm050_attr_list
[idx
]->attr
.name
, err
);
2122 /*----------------------------------------------------------------------------*/
2123 static int bmm050_delete_attr(struct device_driver
*driver
)
2126 int num
= (int)(sizeof(bmm050_attr_list
)/sizeof(bmm050_attr_list
[0]));
2133 for(idx
= 0; idx
< num
; idx
++)
2135 driver_remove_file(driver
, bmm050_attr_list
[idx
]);
2141 /*----------------------------------------------------------------------------*/
2142 static int bmm050_open(struct inode
*inode
, struct file
*file
)
2144 struct bmm050_i2c_data
*obj
= i2c_get_clientdata(this_client
);
2147 if(atomic_read(&obj
->trace
) & MMC_CTR_DEBUG
)
2149 MSE_LOG("Open device node:bmm050\n");
2151 ret
= nonseekable_open(inode
, file
);
2155 /*----------------------------------------------------------------------------*/
2156 static int bmm050_release(struct inode
*inode
, struct file
*file
)
2158 struct bmm050_i2c_data
*obj
= i2c_get_clientdata(this_client
);
2160 if(atomic_read(&obj
->trace
) & MMC_CTR_DEBUG
)
2162 MSE_LOG("Release device node:bmm050\n");
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
)
2171 void __user
*argp
= (void __user
*)arg
;
2173 /* NOTE: In this function the size of "char" should be 1-byte. */
2174 char buff
[BMM050_BUFSIZE
]; /* for chip information */
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 */
2180 struct bmm050_i2c_data
*clientdata
= i2c_get_clientdata(this_client
);
2181 hwm_sensor_data osensor_data
;
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
)))
2194 MSE_ERR("copy_to_user failed.");
2199 case ECOMPASS_IOC_GET_DELAY
: //used by daemon
2200 if(copy_to_user(argp
, &bmm050d_delay
, sizeof(bmm050d_delay
)))
2202 MSE_ERR("copy_to_user failed.");
2205 /* clear the flag */
2206 mutex_lock(&uplink_event_flag_mutex
);
2207 if ((uplink_event_flag
& BMMDRV_ULEVT_FLAG_M_DELAY
) != 0)
2209 uplink_event_flag
&= ~BMMDRV_ULEVT_FLAG_M_DELAY
;
2211 else if ((uplink_event_flag
& BMMDRV_ULEVT_FLAG_O_DELAY
) != 0)
2213 uplink_event_flag
&= ~BMMDRV_ULEVT_FLAG_O_DELAY
;
2215 mutex_unlock(&uplink_event_flag_mutex
);
2216 /* wake up the wait queue */
2217 wake_up(&uplink_event_flag_wq
);
2220 case ECOMPASS_IOC_SET_YPR
: //used by daemon
2223 MSE_ERR("invalid argument.");
2226 if(copy_from_user(value
, argp
, sizeof(value
)))
2228 MSE_ERR("copy_from_user failed.");
2231 ECS_SaveData(value
);
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
)))
2238 MSE_ERR("copy_to_user failed.");
2241 /* clear the flag */
2242 mutex_lock(&uplink_event_flag_mutex
);
2243 if ((uplink_event_flag
& BMMDRV_ULEVT_FLAG_M_ACTIVE
) != 0)
2245 uplink_event_flag
&= ~BMMDRV_ULEVT_FLAG_M_ACTIVE
;
2247 mutex_unlock(&uplink_event_flag_mutex
);
2248 /* wake up the wait queue */
2249 wake_up(&uplink_event_flag_wq
);
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
)))
2256 MSE_ERR("copy_to_user failed.");
2259 /* clear the flag */
2260 mutex_lock(&uplink_event_flag_mutex
);
2261 if ((uplink_event_flag
& BMMDRV_ULEVT_FLAG_O_ACTIVE
) != 0)
2263 uplink_event_flag
&= ~BMMDRV_ULEVT_FLAG_O_ACTIVE
;
2265 mutex_unlock(&uplink_event_flag_mutex
);
2266 /* wake up the wait queue */
2267 wake_up(&uplink_event_flag_wq
);
2271 case MSENSOR_IOCTL_READ_CHIPINFO
: //reserved
2274 MSE_ERR( "IO parameter pointer is NULL!\r\n");
2278 bmm050_ReadChipInfo(buff
, BMM050_BUFSIZE
);
2279 if(copy_to_user(argp
, buff
, strlen(buff
)+1))
2285 case MSENSOR_IOCTL_READ_SENSORDATA
: //used by MTK ftm or engineering mode
2288 MSE_ERR( "IO parameter pointer is NULL!\r\n");
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))
2299 case ECOMPASS_IOC_GET_LAYOUT
: //used by daemon ?
2300 status
= atomic_read(&clientdata
->layout
);
2301 if(copy_to_user(argp
, &status
, sizeof(status
)))
2303 MSE_ERR("copy_to_user failed.");
2308 case MSENSOR_IOCTL_SENSOR_ENABLE
: //used by MTK ftm
2311 MSE_ERR( "IO parameter pointer is NULL!\r\n");
2314 if(copy_from_user(&enable
, argp
, sizeof(enable
)))
2316 MSE_ERR("copy_from_user failed.");
2321 printk( "MSENSOR_IOCTL_SENSOR_ENABLE enable=%d!\r\n",enable
);
2324 atomic_set(&o_flag
, 1);
2325 atomic_set(&open_flag
, 1);
2329 atomic_set(&o_flag
, 0);
2330 if(atomic_read(&m_flag
) == 0)
2332 atomic_set(&open_flag
, 0);
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
);
2346 case MSENSOR_IOCTL_READ_FACTORY_SENSORDATA
: //used by MTK ftm
2349 MSE_ERR( "IO parameter pointer is NULL!\r\n");
2353 mutex_lock(&sensor_data_mutex
);
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
;
2361 mutex_unlock(&sensor_data_mutex
);
2362 if(copy_to_user(argp
, &osensor_data
, sizeof(hwm_sensor_data
)))
2369 MSE_ERR( "%s not supported = 0x%04x", __FUNCTION__
, cmd
);
2370 return -ENOIOCTLCMD
;
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
,
2383 /*----------------------------------------------------------------------------*/
2384 static struct miscdevice bmm050_device
= {
2385 .minor
= MISC_DYNAMIC_MINOR
,
2387 .fops
= &bmm050_fops
,
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
)
2395 hwm_sensor_data
* msensor_data
;
2398 struct i2c_client
*client
= this_client
;
2399 struct bmm050_i2c_data
*data
= i2c_get_clientdata(client
);
2403 if(atomic_read(&data
->trace
) & MMC_FUN_DEBUG
)
2411 if((buff_in
== NULL
) || (size_in
< sizeof(int)))
2413 MSE_ERR( "Set delay parameter error!\n");
2418 value
= *(int *)buff_in
;
2425 bmm050d_delay
= value
;
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
);
2437 if((buff_in
== NULL
) || (size_in
< sizeof(int)))
2439 MSE_ERR( "Enable sensor parameter error!\n");
2445 value
= *(int *)buff_in
;
2449 atomic_set(&m_flag
, 1);
2450 atomic_set(&open_flag
, 1);
2454 atomic_set(&m_flag
, 0);
2455 if(atomic_read(&o_flag
) == 0)
2457 atomic_set(&open_flag
, 0);
2462 bmm050_SetPowerMode(this_client
, (value
== 1));
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
);
2473 case SENSOR_GET_DATA
:
2474 if((buff_out
== NULL
) || (size_out
< sizeof(hwm_sensor_data
)))
2476 MSE_ERR( "get sensor data parameter error!\n");
2481 msensor_data
= (hwm_sensor_data
*)buff_out
;
2482 mutex_lock(&sensor_data_mutex
);
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
;
2490 mutex_unlock(&sensor_data_mutex
);
2492 if(atomic_read(&data
->trace
) & MMC_HWM_DEBUG
)
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
);
2502 MSE_ERR( "msensor operate function no this parameter %d!\n", command
);
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
)
2516 hwm_sensor_data
* osensor_data
;
2518 struct i2c_client
*client
= this_client
;
2519 struct bmm050_i2c_data
*data
= i2c_get_clientdata(client
);
2523 if(atomic_read(&data
->trace
) & MMC_FUN_DEBUG
)
2532 if((buff_in
== NULL
) || (size_in
< sizeof(int)))
2534 MSE_ERR( "Set delay parameter error!\n");
2539 value
= *(int *)buff_in
;
2546 bmm050d_delay
= value
;
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
);
2558 if((buff_in
== NULL
) || (size_in
< sizeof(int)))
2560 MSE_ERR( "Enable sensor parameter error!\n");
2566 value
= *(int *)buff_in
;
2570 atomic_set(&o_flag
, 1);
2571 atomic_set(&open_flag
, 1);
2575 atomic_set(&o_flag
, 0);
2576 if(atomic_read(&m_flag
) == 0)
2578 atomic_set(&open_flag
, 0);
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
);
2592 case SENSOR_GET_DATA
:
2593 if((buff_out
== NULL
) || (size_out
< sizeof(hwm_sensor_data
)))
2595 MSE_ERR( "get sensor data parameter error!\n");
2600 osensor_data
= (hwm_sensor_data
*)buff_out
;
2601 mutex_lock(&sensor_data_mutex
);
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
;
2609 mutex_unlock(&sensor_data_mutex
);
2611 if(atomic_read(&data
->trace
) & MMC_HWM_DEBUG
)
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
);
2621 MSE_ERR( "osensor operate function no this parameter %d!\n", command
);
2629 /*----------------------------------------------------------------------------*/
2630 static void bmm050_restore_hw_cfg(struct i2c_client
*client
)
2632 struct bmm050_i2c_data
*obj
= i2c_get_clientdata(client
);
2634 if (obj
->op_mode
> 3)
2636 obj
->op_mode
= BMC050_SLEEP_MODE
;
2638 bmm050api_set_functional_state(obj
->op_mode
);
2640 bmm050api_set_datarate(obj
->odr
);
2641 //mdelay(BMM_I2C_WRITE_DELAY_TIME);
2643 bmm050api_set_repetitions_XY(obj
->rept_xy
);
2644 //mdelay(BMM_I2C_WRITE_DELAY_TIME);
2646 bmm050api_set_repetitions_Z(obj
->rept_z
);
2647 //mdelay(BMM_I2C_WRITE_DELAY_TIME);
2650 /*----------------------------------------------------------------------------*/
2651 #ifndef CONFIG_HAS_EARLYSUSPEND
2652 /*----------------------------------------------------------------------------*/
2653 static int bmm050_suspend(struct i2c_client
*client
, pm_message_t msg
)
2655 struct bmm050_i2c_data
*obj
= i2c_get_clientdata(client
)
2658 if(msg
.event
== PM_EVENT_SUSPEND
)
2660 bmm050_SetPowerMode(obj
->client
, FALSE
);
2661 bmm050_power(obj
->hw
, 0);
2665 /*----------------------------------------------------------------------------*/
2666 static int bmm050_resume(struct i2c_client
*client
)
2668 struct bmm050_i2c_data
*obj
= i2c_get_clientdata(client
)
2670 bmm050_power(obj
->hw
, 1);
2671 bmm050_SetPowerMode(obj
->client
, TRUE
);
2674 /*----------------------------------------------------------------------------*/
2675 #else /*CONFIG_HAS_EARLY_SUSPEND is defined*/
2676 /*----------------------------------------------------------------------------*/
2677 static void bmm050_early_suspend(struct early_suspend
*h
)
2679 struct bmm050_i2c_data
*obj
= container_of(h
, struct bmm050_i2c_data
, early_drv
);
2685 MSE_ERR( "null pointer!!\n");
2689 bmm050_SetPowerMode(obj
->client
, FALSE
);
2690 bmm050_power(obj
->hw
, 0);
2692 /*----------------------------------------------------------------------------*/
2693 static void bmm050_late_resume(struct early_suspend
*h
)
2695 struct bmm050_i2c_data
*obj
= container_of(h
, struct bmm050_i2c_data
, early_drv
);
2700 MSE_ERR( "null pointer!!\n");
2704 bmm050_power(obj
->hw
, 1);
2705 bmm050_SetPowerMode(obj
->client
, TRUE
);
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
)
2714 int try_times
= BMM_MAX_RETRY_WAKEUP
;
2715 u8 data
[2] = {BMC050_POWER_CNTL
, 0x01};
2718 MSE_LOG("waking up the chip...");
2721 err
= i2c_master_send(client
, data
, 2);
2722 mdelay(BMM_I2C_WRITE_DELAY_TIME
);
2724 err
= hwmsen_read_block(client
, BMC050_POWER_CNTL
, &dummy
, 1);
2725 if (data
[1] == dummy
)
2732 MSE_LOG("wake up result: %s, tried times: %d",
2733 (try_times
> 0) ? "succeed" : "fail",
2734 BMM_MAX_RETRY_WAKEUP
- try_times
+ 1);
2736 err
= (try_times
> 0) ? 0 : -1;
2740 /*----------------------------------------------------------------------------*/
2741 static int bmm050_checkchipid(struct i2c_client
*client
)
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
);
2750 if ((chip_id
& 0xff) != SENSOR_CHIP_ID_BMM
)
2759 /*----------------------------------------------------------------------------*/
2760 static char bmm050_i2c_read_wrapper(u8 dev_addr
, u8 reg_addr
, u8
*data
, u8 len
)
2762 return hwmsen_read_block(this_client
, reg_addr
, data
, len
);
2764 /*----------------------------------------------------------------------------*/
2765 static char bmm050_i2c_write_wrapper(u8 dev_addr
, u8 reg_addr
, u8
*data
, u8 len
)
2767 u8 buff
[BMM050_BUFSIZE
+ 1];
2769 if (len
> BMM050_BUFSIZE
)
2775 memcpy(buff
+1, data
, len
);
2776 if (i2c_master_send(this_client
, buff
, len
+1) != (len
+1))
2778 /* I2C transfer error */
2786 /*----------------------------------------------------------------------------*/
2787 static void bmm050_delay(u32 msec
)
2791 /*----------------------------------------------------------------------------*/
2792 static int bmm050_init_client(struct i2c_client
*client
)
2794 struct bmm050_i2c_data
*obj
= i2c_get_clientdata(client
);
2796 MSE_ERR( "ivy bmm050_init_client");
2798 res
= bmm050_wakeup(client
);
2803 MSE_ERR( "ivy bmm050_checkchipid");
2804 res
= bmm050_checkchipid(client
);
2809 MSE_LOG("check chip ID ok");
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
);
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
;
2823 res
= bmm050api_set_functional_state(BMC050_SUSPEND_MODE
);
2831 /*----------------------------------------------------------------------------*/
2832 //static int bmm050_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info)
2834 // strcpy(info->type, BMM050_DEV_NAME);
2838 /*----------------------------------------------------------------------------*/
2839 static int bmm050_m_enable(int en
)
2842 printk("bmm050_m_enable++\n");
2846 atomic_set(&m_flag
, 1);
2847 atomic_set(&open_flag
, 1);
2851 atomic_set(&m_flag
, 0);
2852 if(atomic_read(&o_flag
) == 0)
2854 atomic_set(&open_flag
, 0);
2859 bmm050_SetPowerMode(this_client
, (value
== 1));
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");
2871 static int bmm050_m_set_delay(u64 ns
)
2874 printk("bmm050_m_set_delay++\n");
2875 value
= (int)ns
/1000/1000;
2882 bmm050d_delay
= value
;
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");
2893 static int bmm050_m_open_report_data(int open
)
2898 static int bmm050_o_enable(int en
)
2901 printk("bmm050_o_enable++\n");
2902 bmm050_m_enable(value
);
2905 atomic_set(&o_flag
, 1);
2906 atomic_set(&open_flag
, 1);
2910 atomic_set(&o_flag
, 0);
2911 if(atomic_read(&m_flag
) == 0)
2913 atomic_set(&open_flag
, 0);
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");
2928 static int bmm050_o_set_delay(u64 ns
)
2931 printk("bmm050_o_set_delay++\n");
2932 value
= (int)ns
/1000/1000;
2939 bmm050d_delay
= value
;
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");
2951 static int bmm050_o_open_report_data(int open
)
2956 static int bmm050_o_get_data(int* x
,int* y
,int* z
, int* status
)
2958 mutex_lock(&sensor_data_mutex
);
2960 *x
= sensor_data
[8];
2961 *y
= sensor_data
[9];
2962 *z
= sensor_data
[10];
2963 *status
= sensor_data
[11];
2965 mutex_unlock(&sensor_data_mutex
);
2969 static int bmm050_m_get_data(int* x
,int* y
,int* z
, int* status
)
2971 mutex_lock(&sensor_data_mutex
);
2973 *x
= sensor_data
[4];
2974 *y
= sensor_data
[5];
2975 *z
= sensor_data
[6];
2976 *status
= sensor_data
[7];
2978 mutex_unlock(&sensor_data_mutex
);
2983 /*----------------------------------------------------------------------------*/
2984 static int bmm050_i2c_probe(struct i2c_client
*client
, const struct i2c_device_id
*id
)
2986 struct i2c_client
*new_client
;
2987 struct bmm050_i2c_data
*data
;
2989 struct mag_control_path ctl
={0};
2990 struct mag_data_path mag_data
={0};
2992 if(!(data
= kmalloc(sizeof(struct bmm050_i2c_data
), GFP_KERNEL
)))
2997 memset(data
, 0, sizeof(struct bmm050_i2c_data
));
2999 data
->hw
= get_cust_mag_hw();
3000 if((err
= hwmsen_get_convert(data
->hw
->direction
, &data
->cvt
)))
3002 MSE_ERR("invalid direction: %d\n", data
->hw
->direction
);
3005 atomic_set(&data
->layout
, data
->hw
->direction
);
3006 atomic_set(&data
->trace
, 0);
3008 mutex_init(&sensor_data_mutex
);
3009 mutex_init(&uplink_event_flag_mutex
);
3011 init_waitqueue_head(&open_wq
);
3012 init_waitqueue_head(&uplink_event_flag_wq
);
3014 data
->client
= client
;
3015 new_client
= data
->client
;
3016 i2c_set_clientdata(new_client
, data
);
3018 this_client
= new_client
;
3021 if ((err
= bmm050_init_client(this_client
)))
3023 MSE_ERR("fail to initialize client");
3024 goto exit_client_failed
;
3027 /* Register sysfs attribute */
3028 if((err
= bmm050_create_attr(&(bmm050_init_info
.platform_diver_addr
->driver
))))
3030 MSE_ERR("create attribute err = %d\n", err
);
3031 goto exit_sysfs_create_group_failed
;
3034 if((err
= misc_register(&bmm050_device
)))
3036 MSE_ERR("bmm050_device register failed\n");
3037 goto exit_misc_device_register_failed
;
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;
3048 err
= mag_register_control_path(&ctl
);
3051 MAG_ERR("register mag control path err\n");
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
;
3060 err
= mag_register_data_path(&mag_data
);
3063 MAG_ERR("register data control path err\n");
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
);
3074 bmm050_init_flag
=1;
3075 MSE_LOG("%s: OK\n", __func__
);
3079 exit_sysfs_create_group_failed
:
3080 exit_misc_device_register_failed
:
3084 MSE_ERR( "%s: err = %d\n", __func__
, err
);
3087 /*----------------------------------------------------------------------------*/
3088 static int bmm050_i2c_remove(struct i2c_client
*client
)
3090 struct bmm050_i2c_data
*obj
= i2c_get_clientdata(client
);
3092 if(bmm050_delete_attr(&(bmm050_init_info
.platform_diver_addr
->driver
)))
3094 MSE_ERR( "bmm050_delete_attr fail");
3097 #ifdef CONFIG_HAS_EARLYSUSPEND
3098 unregister_early_suspend(&obj
->early_drv
);
3100 bmm050api_set_functional_state(BMC050_SUSPEND_MODE
);
3102 i2c_unregister_device(client
);
3104 misc_deregister(&bmm050_device
);
3107 /*----------------------------------------------------------------------------*/
3108 static struct i2c_driver bmm050_i2c_driver
= {
3110 // .owner = THIS_MODULE,
3111 .name
= BMM050_DEV_NAME
,
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
,
3120 .id_table
= bmm050_i2c_id
,
3121 // .address_data = &bmm050_addr_data,
3123 /*----------------------------------------------------------------------------*/
3124 /*----------------------------------------------------------------------------*/
3125 static int bmm050_remove(void)
3127 struct mag_hw
*hw
= get_cust_mag_hw();
3129 i2c_del_driver(&bmm050_i2c_driver
);
3130 bmm050_power(hw
, 0);
3133 /*----------------------------------------------------------------------------*/
3134 static int bmm050_local_init(void)
3136 struct mag_hw
*hw
= get_cust_mag_hw();
3137 //printk("fwq loccal init+++\n");
3139 bmm050_power(hw
, 1);
3140 if(i2c_add_driver(&bmm050_i2c_driver
))
3142 MSE_ERR("add driver error\n");
3145 if(-1 == bmm050_init_flag
)
3149 //printk("fwq loccal init---\n");
3153 static int __init
bmm050_init(void)
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
);
3161 /*----------------------------------------------------------------------------*/
3162 static void __exit
bmm050_exit(void)
3166 /*----------------------------------------------------------------------------*/
3167 module_init(bmm050_init
);
3168 module_exit(bmm050_exit
);
3170 MODULE_AUTHOR("hongji.zhou@bosch-sensortec.com");
3171 MODULE_DESCRIPTION("bmm050 compass driver");
3172 MODULE_LICENSE("GPL");