1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * MCube mc3230 acceleration sensor driver
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2011 MCube Inc.,
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or modify
7*4882a593Smuzhiyun * it under the terms of the GNU General Public License as published by
8*4882a593Smuzhiyun * the Free Software Foundation; either version 2 of the License, or
9*4882a593Smuzhiyun * (at your option) any later version.
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * This program is distributed in the hope that it will be useful,
12*4882a593Smuzhiyun * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*4882a593Smuzhiyun * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*4882a593Smuzhiyun * GNU General Public License for more details.
15*4882a593Smuzhiyun */
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include <linux/interrupt.h>
18*4882a593Smuzhiyun #include <linux/i2c.h>
19*4882a593Smuzhiyun #include <linux/slab.h>
20*4882a593Smuzhiyun #include <linux/irq.h>
21*4882a593Smuzhiyun #include <linux/miscdevice.h>
22*4882a593Smuzhiyun #include <linux/gpio.h>
23*4882a593Smuzhiyun #include <linux/uaccess.h>
24*4882a593Smuzhiyun #include <linux/atomic.h>
25*4882a593Smuzhiyun #include <linux/delay.h>
26*4882a593Smuzhiyun #include <linux/input.h>
27*4882a593Smuzhiyun #include <linux/workqueue.h>
28*4882a593Smuzhiyun #include <linux/freezer.h>
29*4882a593Smuzhiyun #include <linux/of_gpio.h>
30*4882a593Smuzhiyun #ifdef CONFIG_HAS_EARLYSUSPEND
31*4882a593Smuzhiyun #include <linux/earlysuspend.h>
32*4882a593Smuzhiyun #endif
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #include <linux/sensor-dev.h>
35*4882a593Smuzhiyun #include <linux/mc3230.h>
36*4882a593Smuzhiyun #include <linux/wakelock.h>
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun #define MITECH_SENSOR_DBG
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun static int sensor_active(struct i2c_client *client, int enable, int rate);
41*4882a593Smuzhiyun #define MC32X0_XOUT_REG 0x00
42*4882a593Smuzhiyun #define MC32X0_YOUT_REG 0x01
43*4882a593Smuzhiyun #define MC32X0_ZOUT_REG 0x02
44*4882a593Smuzhiyun #define MC32X0_Tilt_Status_REG 0x03
45*4882a593Smuzhiyun #define MC32X0_Sampling_Rate_Status_REG 0x04
46*4882a593Smuzhiyun #define MC32X0_Sleep_Count_REG 0x05
47*4882a593Smuzhiyun #define MC32X0_Interrupt_Enable_REG 0x06
48*4882a593Smuzhiyun #define MC32X0_Mode_Feature_REG 0x07
49*4882a593Smuzhiyun #define MC32X0_Sample_Rate_REG 0x08
50*4882a593Smuzhiyun #define MC32X0_Tap_Detection_Enable_REG 0x09
51*4882a593Smuzhiyun #define MC32X0_TAP_Dwell_Reject_REG 0x0a
52*4882a593Smuzhiyun #define MC32X0_DROP_Control_Register_REG 0x0b
53*4882a593Smuzhiyun #define MC32X0_SHAKE_Debounce_REG 0x0c
54*4882a593Smuzhiyun #define MC32X0_XOUT_EX_L_REG 0x0d
55*4882a593Smuzhiyun #define MC32X0_XOUT_EX_H_REG 0x0e
56*4882a593Smuzhiyun #define MC32X0_YOUT_EX_L_REG 0x0f
57*4882a593Smuzhiyun #define MC32X0_YOUT_EX_H_REG 0x10
58*4882a593Smuzhiyun #define MC32X0_ZOUT_EX_L_REG 0x11
59*4882a593Smuzhiyun #define MC32X0_ZOUT_EX_H_REG 0x12
60*4882a593Smuzhiyun #define MC32X0_CHIP_ID_REG 0x18
61*4882a593Smuzhiyun #define MC32X0_RANGE_Control_REG 0x20
62*4882a593Smuzhiyun #define MC32X0_SHAKE_Threshold_REG 0x2B
63*4882a593Smuzhiyun #define MC32X0_UD_Z_TH_REG 0x2C
64*4882a593Smuzhiyun #define MC32X0_UD_X_TH_REG 0x2D
65*4882a593Smuzhiyun #define MC32X0_RL_Z_TH_REG 0x2E
66*4882a593Smuzhiyun #define MC32X0_RL_Y_TH_REG 0x2F
67*4882a593Smuzhiyun #define MC32X0_FB_Z_TH_REG 0x30
68*4882a593Smuzhiyun #define MC32X0_DROP_Threshold_REG 0x31
69*4882a593Smuzhiyun #define MC32X0_TAP_Threshold_REG 0x32
70*4882a593Smuzhiyun #define MC32X0_MODE_SLEEP 0x00
71*4882a593Smuzhiyun #define MC32X0_MODE_WAKEUP 0x01
72*4882a593Smuzhiyun #define MODE_CHANGE_DELAY_MS 100
73*4882a593Smuzhiyun #define MC3230_MODE_MITECH 0X58
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun #define MC3230_MODE_BITS 0x03
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun #define MC3230_PRECISION 8
78*4882a593Smuzhiyun #define MC3230_RANGE 1500000
79*4882a593Smuzhiyun #define MC3210_RANGE 8000000
80*4882a593Smuzhiyun #define MC3230_BOUNDARY (0x1 << (MC3230_PRECISION - 1))
81*4882a593Smuzhiyun #define MC3230_GRAVITY_STEPS (MC3230_RANGE/MC3230_BOUNDARY)
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun #define MC3236_RANGE 2000000
84*4882a593Smuzhiyun #define MC3236_GRAVITY_STEP (MC3236_RANGE/MC3230_BOUNDARY)
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun /* 8bit data */
87*4882a593Smuzhiyun #define MC3210_PRECISION 14
88*4882a593Smuzhiyun #define MC3210_BOUNDARY (0x1 << (MC3210_PRECISION - 1))
89*4882a593Smuzhiyun /* 110 2g full scale range */
90*4882a593Smuzhiyun #define MC3210_GRAVITY_STEP (MC3210_RANGE/MC3210_BOUNDARY)
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun /* rate */
93*4882a593Smuzhiyun #define MC3230_RATE_1 0x07
94*4882a593Smuzhiyun #define MC3230_RATE_2 0x06
95*4882a593Smuzhiyun #define MC3230_RATE_4 0x05
96*4882a593Smuzhiyun #define MC3230_RATE_8 0x04
97*4882a593Smuzhiyun #define MC3230_RATE_16 0x03
98*4882a593Smuzhiyun #define MC3230_RATE_32 0x02
99*4882a593Smuzhiyun #define MC3230_RATE_64 0x01
100*4882a593Smuzhiyun #define MC3230_RATE_120 0x00
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun #define MC32X0_AXIS_X 0
103*4882a593Smuzhiyun #define MC32X0_AXIS_Y 1
104*4882a593Smuzhiyun #define MC32X0_AXIS_Z 2
105*4882a593Smuzhiyun #define MC32X0_AXES_NUM 3
106*4882a593Smuzhiyun #define MC32X0_DATA_LEN 6
107*4882a593Smuzhiyun #define MC32X0_DEV_NAME "MC32X0"
108*4882a593Smuzhiyun #define GRAVITY_EARTH_1000 9807
109*4882a593Smuzhiyun #define IS_MC3230 1
110*4882a593Smuzhiyun #define IS_MC3210 2
111*4882a593Smuzhiyun #define IS_MC2234 3
112*4882a593Smuzhiyun #define IS_MC3236 4
113*4882a593Smuzhiyun #define IS_MC3413 5
114*4882a593Smuzhiyun #define IS_MC3416 6
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun static const char backup_calib_path[] = "/data/misc/mcube-calib.txt";
117*4882a593Smuzhiyun static const char calib_path[] =
118*4882a593Smuzhiyun "/data/data/com.mcube.acc/files/mcube-calib.txt";
119*4882a593Smuzhiyun static char backup_buf[64];
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun static GSENSOR_VECTOR3D gsensor_gain;
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun static struct file *fd_file;
124*4882a593Smuzhiyun static int load_cali_flg;
125*4882a593Smuzhiyun static bool READ_FROM_BACKUP;
126*4882a593Smuzhiyun static mm_segment_t oldfs;
127*4882a593Smuzhiyun static unsigned char offset_buf[9];
128*4882a593Smuzhiyun static signed int offset_data[3];
129*4882a593Smuzhiyun static s16 G_RAW_DATA[3];
130*4882a593Smuzhiyun static signed int gain_data[3];
131*4882a593Smuzhiyun static signed int enable_RBM_calibration;
132*4882a593Smuzhiyun static unsigned char mc32x0_type;
133*4882a593Smuzhiyun static int g_value;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun #define mcprintkreg(x...)
136*4882a593Smuzhiyun #define mcprintkfunc(x...)
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun #define GSE_TAG "[Gsensor] "
139*4882a593Smuzhiyun #define GSE_FUN(f) pr_info(GSE_TAG"%s\n", __func__)
140*4882a593Smuzhiyun #define GSE_ERR(fmt, args...) pr_info(GSE_TAG"%s %d : "fmt, \
141*4882a593Smuzhiyun __func__, __LINE__, ##args)
142*4882a593Smuzhiyun #define GSE_LOG(fmt, args...) pr_info(GSE_TAG fmt, ##args)
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun #define MC3230_SPEED (200 * 1000)
145*4882a593Smuzhiyun #define MC3230_DEVID 0x01
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun /* Addresses to scan -- protected by sense_data_mutex */
148*4882a593Smuzhiyun static struct i2c_client *this_client;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun #ifdef CONFIG_HAS_EARLYSUSPEND
151*4882a593Smuzhiyun static struct early_suspend mc3230_early_suspend;
152*4882a593Smuzhiyun #endif
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun /* status */
155*4882a593Smuzhiyun #define MC3230_OPEN 1
156*4882a593Smuzhiyun #define MC3230_CLOSE 0
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun struct hwmsen_convert {
159*4882a593Smuzhiyun s8 sign[3];
160*4882a593Smuzhiyun u8 map[3];
161*4882a593Smuzhiyun };
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun struct mc3230_data {
164*4882a593Smuzhiyun struct sensor_private_data *g_sensor_private_data;
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun char status;
167*4882a593Smuzhiyun char curr_rate;
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun /* +1: for 4-byte alignment */
170*4882a593Smuzhiyun s16 offset[MC32X0_AXES_NUM + 1];
171*4882a593Smuzhiyun s16 data[MC32X0_AXES_NUM + 1];
172*4882a593Smuzhiyun s16 cali_sw[MC32X0_AXES_NUM + 1];
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun struct hwmsen_convert cvt;
175*4882a593Smuzhiyun };
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun static int MC32X0_WriteCalibration(struct i2c_client *client,
178*4882a593Smuzhiyun int dat[MC32X0_AXES_NUM]);
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun static int mc3230_write_reg(struct i2c_client *client, int addr, int value);
181*4882a593Smuzhiyun static int mc3230_read_block(struct i2c_client *client, char reg, char *rxData,
182*4882a593Smuzhiyun int length);
183*4882a593Smuzhiyun static int mc3230_active(struct i2c_client *client, int enable);
184*4882a593Smuzhiyun static void MC32X0_rbm(struct i2c_client *client, int enable);
185*4882a593Smuzhiyun static int init_3230_ctl_data(struct i2c_client *client);
186*4882a593Smuzhiyun
openFile(const char * path,int flag,int mode)187*4882a593Smuzhiyun struct file *openFile(const char *path, int flag, int mode)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun struct file *fp;
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun fp = filp_open(path, flag, mode);
192*4882a593Smuzhiyun if (IS_ERR(fp) || !fp->f_op)
193*4882a593Smuzhiyun return NULL;
194*4882a593Smuzhiyun else
195*4882a593Smuzhiyun return fp;
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun
readFile(struct file * fp,char * buf,int readlen)198*4882a593Smuzhiyun static int readFile(struct file *fp, char *buf, int readlen)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun if (fp->f_op && fp->f_op->read)
201*4882a593Smuzhiyun return fp->f_op->read(fp, buf, readlen, &fp->f_pos);
202*4882a593Smuzhiyun else
203*4882a593Smuzhiyun return -1;
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun
writeFile(struct file * fp,char * buf,int writelen)206*4882a593Smuzhiyun static int writeFile(struct file *fp, char *buf, int writelen)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun if (fp->f_op && fp->f_op->write)
209*4882a593Smuzhiyun return fp->f_op->write(fp, buf, writelen, &fp->f_pos);
210*4882a593Smuzhiyun else
211*4882a593Smuzhiyun return -1;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun
closeFile(struct file * fp)214*4882a593Smuzhiyun static int closeFile(struct file *fp)
215*4882a593Smuzhiyun {
216*4882a593Smuzhiyun filp_close(fp, NULL);
217*4882a593Smuzhiyun return 0;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
initKernelEnv(void)220*4882a593Smuzhiyun static void initKernelEnv(void)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun oldfs = get_fs();
223*4882a593Smuzhiyun set_fs(KERNEL_DS);
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun static struct mc3230_data g_mc3230_data = { 0 };
get_3230_ctl_data(void)227*4882a593Smuzhiyun static struct mc3230_data *get_3230_ctl_data(void)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun return &g_mc3230_data;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
mcube_read_cali_file(struct i2c_client * client)232*4882a593Smuzhiyun static int mcube_read_cali_file(struct i2c_client *client)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun int cali_data[3];
235*4882a593Smuzhiyun int err = 0;
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun READ_FROM_BACKUP = false;
238*4882a593Smuzhiyun initKernelEnv();
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun fd_file =
241*4882a593Smuzhiyun openFile("/data/data/com.mcube.acc/files/mcube-calib.txt", 0, 0);
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun if (!fd_file) {
244*4882a593Smuzhiyun fd_file = openFile(backup_calib_path, O_RDONLY, 0);
245*4882a593Smuzhiyun if (fd_file)
246*4882a593Smuzhiyun READ_FROM_BACKUP = true;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun if (!fd_file) {
250*4882a593Smuzhiyun cali_data[0] = 0;
251*4882a593Smuzhiyun cali_data[1] = 0;
252*4882a593Smuzhiyun cali_data[2] = 0;
253*4882a593Smuzhiyun return 1;
254*4882a593Smuzhiyun } else {
255*4882a593Smuzhiyun memset(backup_buf, 0, 64);
256*4882a593Smuzhiyun err = readFile(fd_file, backup_buf, 128);
257*4882a593Smuzhiyun if (err > 0)
258*4882a593Smuzhiyun GSE_LOG("buf:%s\n", backup_buf);
259*4882a593Smuzhiyun else
260*4882a593Smuzhiyun GSE_LOG("read file error %d\n", err);
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun set_fs(oldfs);
263*4882a593Smuzhiyun closeFile(fd_file);
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun sscanf(backup_buf, "%d %d %d", &cali_data[MC32X0_AXIS_X],
266*4882a593Smuzhiyun &cali_data[MC32X0_AXIS_Y], &cali_data[MC32X0_AXIS_Z]);
267*4882a593Smuzhiyun GSE_LOG("cali_data: %d %d %d\n", cali_data[MC32X0_AXIS_X],
268*4882a593Smuzhiyun cali_data[MC32X0_AXIS_Y], cali_data[MC32X0_AXIS_Z]);
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun MC32X0_WriteCalibration(client, cali_data);
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun return 0;
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun
MC32X0_rbm(struct i2c_client * client,int enable)275*4882a593Smuzhiyun static void MC32X0_rbm(struct i2c_client *client, int enable)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun int err;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun if (enable == 1) {
280*4882a593Smuzhiyun err = mc3230_write_reg(client, 0x07, 0x43);
281*4882a593Smuzhiyun err = mc3230_write_reg(client, 0x14, 0x02);
282*4882a593Smuzhiyun err = mc3230_write_reg(client, 0x07, 0x41);
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun enable_RBM_calibration = 1;
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun GSE_LOG("set rbm!!\n");
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun msleep(220);
289*4882a593Smuzhiyun } else if (enable == 0) {
290*4882a593Smuzhiyun err = mc3230_write_reg(client, 0x07, 0x43);
291*4882a593Smuzhiyun err = mc3230_write_reg(client, 0x14, 0x00);
292*4882a593Smuzhiyun err = mc3230_write_reg(client, 0x07, 0x41);
293*4882a593Smuzhiyun enable_RBM_calibration = 0;
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun GSE_LOG("clear rbm!!\n");
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun msleep(220);
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun
MC32X0_ReadData_RBM(struct i2c_client * client,int data[MC32X0_AXES_NUM])301*4882a593Smuzhiyun static int MC32X0_ReadData_RBM(struct i2c_client *client,
302*4882a593Smuzhiyun int data[MC32X0_AXES_NUM])
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun u8 addr = 0x0d;
305*4882a593Smuzhiyun u8 rbm_buf[MC32X0_DATA_LEN] = { 0 };
306*4882a593Smuzhiyun int err = 0;
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun if (!client) {
309*4882a593Smuzhiyun err = -EINVAL;
310*4882a593Smuzhiyun return err;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun err = mc3230_read_block(client, addr, rbm_buf, 0x06);
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun data[MC32X0_AXIS_X] = (s16)((rbm_buf[0]) | (rbm_buf[1] << 8));
316*4882a593Smuzhiyun data[MC32X0_AXIS_Y] = (s16)((rbm_buf[2]) | (rbm_buf[3] << 8));
317*4882a593Smuzhiyun data[MC32X0_AXIS_Z] = (s16)((rbm_buf[4]) | (rbm_buf[5] << 8));
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun GSE_LOG("rbm_buf<<<<<[%02x %02x %02x %02x %02x %02x]\n", rbm_buf[0],
320*4882a593Smuzhiyun rbm_buf[2], rbm_buf[2], rbm_buf[3], rbm_buf[4], rbm_buf[5]);
321*4882a593Smuzhiyun GSE_LOG("RBM<<<<<[%04x %04x %04x]\n", data[MC32X0_AXIS_X],
322*4882a593Smuzhiyun data[MC32X0_AXIS_Y], data[MC32X0_AXIS_Z]);
323*4882a593Smuzhiyun GSE_LOG("RBM<<<<<[%04d %04d %04d]\n", data[MC32X0_AXIS_X],
324*4882a593Smuzhiyun data[MC32X0_AXIS_Y], data[MC32X0_AXIS_Z]);
325*4882a593Smuzhiyun return err;
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun
mc3230_read_block(struct i2c_client * client,char reg,char * rxData,int length)328*4882a593Smuzhiyun static int mc3230_read_block(struct i2c_client *client, char reg, char *rxData,
329*4882a593Smuzhiyun int length)
330*4882a593Smuzhiyun {
331*4882a593Smuzhiyun int ret = 0;
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun *rxData = reg;
334*4882a593Smuzhiyun ret = sensor_rx_data(client, rxData, length);
335*4882a593Smuzhiyun return ret;
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun
mc3230_write_reg(struct i2c_client * client,int addr,int value)338*4882a593Smuzhiyun static int mc3230_write_reg(struct i2c_client *client, int addr, int value)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun char buffer[3];
341*4882a593Smuzhiyun int ret = 0;
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun buffer[0] = addr;
344*4882a593Smuzhiyun buffer[1] = value;
345*4882a593Smuzhiyun ret = sensor_tx_data(client, &buffer[0], 2);
346*4882a593Smuzhiyun return ret;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun
mc3230_active(struct i2c_client * client,int enable)349*4882a593Smuzhiyun static int mc3230_active(struct i2c_client *client, int enable)
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun int tmp;
352*4882a593Smuzhiyun int ret = 0;
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun if (enable)
355*4882a593Smuzhiyun tmp = 0x01;
356*4882a593Smuzhiyun else
357*4882a593Smuzhiyun tmp = 0x03;
358*4882a593Smuzhiyun mcprintkreg("mc3230_active %s (0x%x)\n", enable ? "active" : "standby",
359*4882a593Smuzhiyun tmp);
360*4882a593Smuzhiyun ret = mc3230_write_reg(client, MC3230_REG_SYSMOD, tmp);
361*4882a593Smuzhiyun return ret;
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun
mc3230_reg_init(struct i2c_client * client)364*4882a593Smuzhiyun static int mc3230_reg_init(struct i2c_client *client)
365*4882a593Smuzhiyun {
366*4882a593Smuzhiyun int ret = 0;
367*4882a593Smuzhiyun int pcode = 0;
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun /* 1: awake 0: standby */
370*4882a593Smuzhiyun mc3230_active(client, 0);
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun pcode = sensor_read_reg(client, MC3230_REG_PRODUCT_CODE);
373*4882a593Smuzhiyun printk(KERN_INFO "mc3230_reg_init pcode=%x\n", pcode);
374*4882a593Smuzhiyun if ((pcode == 0x19) || (pcode == 0x29)) {
375*4882a593Smuzhiyun mc32x0_type = IS_MC3230;
376*4882a593Smuzhiyun } else if ((pcode == 0x90) || (pcode == 0xA8) || (pcode == 0x88)) {
377*4882a593Smuzhiyun mc32x0_type = IS_MC3210;
378*4882a593Smuzhiyun } else if (pcode == 0x59) {
379*4882a593Smuzhiyun mc32x0_type = IS_MC2234;
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun if ((pcode & 0xF1) == 0x60) {
383*4882a593Smuzhiyun mc32x0_type = IS_MC3236;
384*4882a593Smuzhiyun } else if ((pcode & 0xF1) == 0x10) {
385*4882a593Smuzhiyun mc32x0_type = IS_MC3413;
386*4882a593Smuzhiyun } else if ((pcode & 0xF1) == 0x20) {
387*4882a593Smuzhiyun mc32x0_type = IS_MC3416;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun GSE_LOG("MC3230 1, MC3210 2, MC2234 3, MC3236 4, MC3416 5, MC3416 6:mc32x0_type=%d\n", mc32x0_type);
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun if ((mc32x0_type == IS_MC3230) || (mc32x0_type == IS_MC2234)) {
393*4882a593Smuzhiyun ret = sensor_write_reg(client, 0x20, 0x32);
394*4882a593Smuzhiyun } else if (mc32x0_type == IS_MC3236) {
395*4882a593Smuzhiyun ret = sensor_write_reg(client, 0x20, 0x02);
396*4882a593Smuzhiyun } else if (mc32x0_type == IS_MC3210) {
397*4882a593Smuzhiyun ret = sensor_write_reg(client, 0x20, 0x3F);
398*4882a593Smuzhiyun } else if (mc32x0_type == IS_MC3413) {
399*4882a593Smuzhiyun ret = sensor_write_reg(client, 0x20, 0x25);
400*4882a593Smuzhiyun } else if (mc32x0_type == IS_MC3416) {
401*4882a593Smuzhiyun ret = sensor_write_reg(client, 0x08, 0x05);
402*4882a593Smuzhiyun ret = sensor_write_reg(client, 0x20, 0x29);
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
405*4882a593Smuzhiyun if ((mc32x0_type == IS_MC3230) || (mc32x0_type == IS_MC2234)) {
406*4882a593Smuzhiyun gsensor_gain.x = gsensor_gain.y = gsensor_gain.z = 86;
407*4882a593Smuzhiyun } else if (mc32x0_type == IS_MC3236) {
408*4882a593Smuzhiyun gsensor_gain.x = gsensor_gain.y = gsensor_gain.z = 64;
409*4882a593Smuzhiyun } else if ((mc32x0_type == IS_MC3210) || (mc32x0_type == IS_MC3413)) {
410*4882a593Smuzhiyun gsensor_gain.x = gsensor_gain.y = gsensor_gain.z = 1024;
411*4882a593Smuzhiyun } else if (mc32x0_type == IS_MC3416) {
412*4882a593Smuzhiyun gsensor_gain.x = gsensor_gain.y = gsensor_gain.z = 4096;
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun return ret;
416*4882a593Smuzhiyun }
init_3230_ctl_data(struct i2c_client * client)417*4882a593Smuzhiyun static int init_3230_ctl_data(struct i2c_client *client)
418*4882a593Smuzhiyun {
419*4882a593Smuzhiyun int err;
420*4882a593Smuzhiyun s16 tmp, x_gain, y_gain, z_gain;
421*4882a593Smuzhiyun s32 x_off, y_off, z_off;
422*4882a593Smuzhiyun struct mc3230_data *mc3230 = get_3230_ctl_data();
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun load_cali_flg = 30;
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun mcprintkfunc("%s enter\n", __func__);
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun this_client = client;
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun mc3230->g_sensor_private_data =
431*4882a593Smuzhiyun (struct sensor_private_data *)i2c_get_clientdata(client);
432*4882a593Smuzhiyun mc3230->curr_rate = MC3230_RATE_16;
433*4882a593Smuzhiyun mc3230->status = MC3230_CLOSE;
434*4882a593Smuzhiyun mc3230->cvt.sign[MC32X0_AXIS_X] = 1;
435*4882a593Smuzhiyun mc3230->cvt.sign[MC32X0_AXIS_Y] = 1;
436*4882a593Smuzhiyun mc3230->cvt.sign[MC32X0_AXIS_Z] = 1;
437*4882a593Smuzhiyun mc3230->cvt.map[MC32X0_AXIS_X] = 0;
438*4882a593Smuzhiyun mc3230->cvt.map[MC32X0_AXIS_Y] = 1;
439*4882a593Smuzhiyun mc3230->cvt.map[MC32X0_AXIS_Z] = 2;
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun sensor_write_reg(client, 0x1b, 0x6d);
442*4882a593Smuzhiyun sensor_write_reg(client, 0x1b, 0x43);
443*4882a593Smuzhiyun msleep(5);
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun sensor_write_reg(client, 0x07, 0x43);
446*4882a593Smuzhiyun sensor_write_reg(client, 0x1C, 0x80);
447*4882a593Smuzhiyun sensor_write_reg(client, 0x17, 0x80);
448*4882a593Smuzhiyun msleep(5);
449*4882a593Smuzhiyun sensor_write_reg(client, 0x1C, 0x00);
450*4882a593Smuzhiyun sensor_write_reg(client, 0x17, 0x00);
451*4882a593Smuzhiyun msleep(5);
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun memset(offset_buf, 0, 9);
454*4882a593Smuzhiyun offset_buf[0] = 0x21;
455*4882a593Smuzhiyun err = sensor_rx_data(client, offset_buf, 9);
456*4882a593Smuzhiyun if (err) {
457*4882a593Smuzhiyun GSE_ERR("error: %d\n", err);
458*4882a593Smuzhiyun return err;
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun tmp = ((offset_buf[1] & 0x3f) << 8) + offset_buf[0];
462*4882a593Smuzhiyun if (tmp & 0x2000)
463*4882a593Smuzhiyun tmp |= 0xc000;
464*4882a593Smuzhiyun x_off = tmp;
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun tmp = ((offset_buf[3] & 0x3f) << 8) + offset_buf[2];
467*4882a593Smuzhiyun if (tmp & 0x2000)
468*4882a593Smuzhiyun tmp |= 0xc000;
469*4882a593Smuzhiyun y_off = tmp;
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun tmp = ((offset_buf[5] & 0x3f) << 8) + offset_buf[4];
472*4882a593Smuzhiyun if (tmp & 0x2000)
473*4882a593Smuzhiyun tmp |= 0xc000;
474*4882a593Smuzhiyun z_off = tmp;
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun /* get x,y,z gain */
477*4882a593Smuzhiyun x_gain = ((offset_buf[1] >> 7) << 8) + offset_buf[6];
478*4882a593Smuzhiyun y_gain = ((offset_buf[3] >> 7) << 8) + offset_buf[7];
479*4882a593Smuzhiyun z_gain = ((offset_buf[5] >> 7) << 8) + offset_buf[8];
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun /* storege the cerrunt offset data with DOT format */
482*4882a593Smuzhiyun offset_data[0] = x_off;
483*4882a593Smuzhiyun offset_data[1] = y_off;
484*4882a593Smuzhiyun offset_data[2] = z_off;
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun /* storege the cerrunt Gain data with GOT format */
487*4882a593Smuzhiyun gain_data[0] = 256 * 8 * 128 / 3 / (40 + x_gain);
488*4882a593Smuzhiyun gain_data[1] = 256 * 8 * 128 / 3 / (40 + y_gain);
489*4882a593Smuzhiyun gain_data[2] = 256 * 8 * 128 / 3 / (40 + z_gain);
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun mc3230_reg_init(this_client);
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun return 0;
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun
mc3230_start_dev(struct i2c_client * client,char rate)496*4882a593Smuzhiyun static int mc3230_start_dev(struct i2c_client *client, char rate)
497*4882a593Smuzhiyun {
498*4882a593Smuzhiyun int ret = 0;
499*4882a593Smuzhiyun struct mc3230_data *mc3230 = get_3230_ctl_data();
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun /* standby */
502*4882a593Smuzhiyun mc3230_active(client, 0);
503*4882a593Smuzhiyun mcprintkreg("mc3230 MC3230_REG_SYSMOD:%x\n",
504*4882a593Smuzhiyun mc3230_read_reg(client, MC3230_REG_SYSMOD));
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun /*data rate */
507*4882a593Smuzhiyun ret = mc3230_write_reg(client, MC3230_REG_RATE_SAMP, rate);
508*4882a593Smuzhiyun mc3230->curr_rate = rate;
509*4882a593Smuzhiyun mcprintkreg("mc3230 MC3230_REG_RATE_SAMP:%x rate=%d\n",
510*4882a593Smuzhiyun mc3230_read_reg(client, MC3230_REG_RATE_SAMP), rate);
511*4882a593Smuzhiyun /*wake */
512*4882a593Smuzhiyun mc3230_active(client, 1);
513*4882a593Smuzhiyun mcprintkreg("mc3230 MC3230_REG_SYSMOD:%x\n",
514*4882a593Smuzhiyun mc3230_read_reg(client, MC3230_REG_SYSMOD));
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun return ret;
517*4882a593Smuzhiyun }
518*4882a593Smuzhiyun
mc3230_start(struct i2c_client * client,char rate)519*4882a593Smuzhiyun static int mc3230_start(struct i2c_client *client, char rate)
520*4882a593Smuzhiyun {
521*4882a593Smuzhiyun struct mc3230_data *mc3230 = get_3230_ctl_data();
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun if (mc3230->status == MC3230_OPEN)
524*4882a593Smuzhiyun return 0;
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun mc3230->status = MC3230_OPEN;
527*4882a593Smuzhiyun rate = 0;
528*4882a593Smuzhiyun return mc3230_start_dev(client, rate);
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun
mc3230_convert_to_int(s16 value)531*4882a593Smuzhiyun static inline int mc3230_convert_to_int(s16 value)
532*4882a593Smuzhiyun {
533*4882a593Smuzhiyun int result = 0;
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun if ((mc32x0_type == IS_MC3230) || (mc32x0_type == IS_MC2234)) {
536*4882a593Smuzhiyun result = value * 192;
537*4882a593Smuzhiyun } else if (mc32x0_type == IS_MC3236) {
538*4882a593Smuzhiyun result = value * 256;
539*4882a593Smuzhiyun } else if ((mc32x0_type == IS_MC3210) || (mc32x0_type == IS_MC3413)) {
540*4882a593Smuzhiyun result = value * 16;
541*4882a593Smuzhiyun } else if (mc32x0_type == IS_MC3416) {
542*4882a593Smuzhiyun result = value * 4;
543*4882a593Smuzhiyun }
544*4882a593Smuzhiyun
545*4882a593Smuzhiyun return result;
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun
mc3230_report_value(struct i2c_client * client,struct sensor_axis * axis)548*4882a593Smuzhiyun static void mc3230_report_value(struct i2c_client *client,
549*4882a593Smuzhiyun struct sensor_axis *axis)
550*4882a593Smuzhiyun {
551*4882a593Smuzhiyun struct sensor_private_data *mc3230 = i2c_get_clientdata(client);
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun if (mc3230->status_cur == SENSOR_OFF)
554*4882a593Smuzhiyun return;
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun if (mc32x0_type == IS_MC2234) {
557*4882a593Smuzhiyun input_report_abs(mc3230->input_dev, ABS_X, (axis->x));
558*4882a593Smuzhiyun input_report_abs(mc3230->input_dev, ABS_Y, -(axis->y));
559*4882a593Smuzhiyun input_report_abs(mc3230->input_dev, ABS_Z, (axis->z));
560*4882a593Smuzhiyun } else if (mc32x0_type == IS_MC3236) {
561*4882a593Smuzhiyun input_report_abs(mc3230->input_dev, ABS_X, -(axis->x));
562*4882a593Smuzhiyun input_report_abs(mc3230->input_dev, ABS_Y, (axis->y));
563*4882a593Smuzhiyun input_report_abs(mc3230->input_dev, ABS_Z, -(axis->z));
564*4882a593Smuzhiyun } else if (mc32x0_type == IS_MC3416) {
565*4882a593Smuzhiyun input_report_abs(mc3230->input_dev, ABS_X, (axis->x));
566*4882a593Smuzhiyun input_report_abs(mc3230->input_dev, ABS_Y, -(axis->y));
567*4882a593Smuzhiyun input_report_abs(mc3230->input_dev, ABS_Z, -(axis->z));
568*4882a593Smuzhiyun } else {
569*4882a593Smuzhiyun input_report_abs(mc3230->input_dev, ABS_X, (axis->y));
570*4882a593Smuzhiyun input_report_abs(mc3230->input_dev, ABS_Y, (axis->x));
571*4882a593Smuzhiyun input_report_abs(mc3230->input_dev, ABS_Z, (axis->z));
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun input_sync(mc3230->input_dev);
575*4882a593Smuzhiyun }
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun static int MC32X0_ReadData(struct i2c_client *client,
578*4882a593Smuzhiyun s16 buffer[MC32X0_AXES_NUM]);
579*4882a593Smuzhiyun
mc3230_get_data(struct i2c_client * client)580*4882a593Smuzhiyun static int mc3230_get_data(struct i2c_client *client)
581*4882a593Smuzhiyun {
582*4882a593Smuzhiyun struct sensor_private_data *sensor =
583*4882a593Smuzhiyun (struct sensor_private_data *)i2c_get_clientdata(client);
584*4882a593Smuzhiyun struct sensor_platform_data *pdata = sensor->pdata;
585*4882a593Smuzhiyun s16 buffer[6];
586*4882a593Smuzhiyun int ret;
587*4882a593Smuzhiyun int x, y, z;
588*4882a593Smuzhiyun int value = 0;
589*4882a593Smuzhiyun static int flag;
590*4882a593Smuzhiyun struct sensor_axis axis;
591*4882a593Smuzhiyun
592*4882a593Smuzhiyun if (load_cali_flg > 0) {
593*4882a593Smuzhiyun ret = mcube_read_cali_file(client);
594*4882a593Smuzhiyun if (ret == 0)
595*4882a593Smuzhiyun load_cali_flg = ret;
596*4882a593Smuzhiyun else
597*4882a593Smuzhiyun load_cali_flg--;
598*4882a593Smuzhiyun }
599*4882a593Smuzhiyun ret = MC32X0_ReadData(client, buffer);
600*4882a593Smuzhiyun if (ret) {
601*4882a593Smuzhiyun GSE_ERR("%s I2C error: ret value=%d", __func__, ret);
602*4882a593Smuzhiyun return -EIO;
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun value = sensor_read_reg(client, 0x20);
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun if (value == 0x00) {
608*4882a593Smuzhiyun static int cnt;
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun if (cnt++ >= 20) {
611*4882a593Smuzhiyun sensor_active(client, 1, 0xff);
612*4882a593Smuzhiyun cnt = 0;
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun g_value = 4;
615*4882a593Smuzhiyun } else if (value == 0x01) {
616*4882a593Smuzhiyun g_value = 2;
617*4882a593Smuzhiyun } else
618*4882a593Smuzhiyun g_value = 1;
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun x = mc3230_convert_to_int(buffer[0]) * g_value;
621*4882a593Smuzhiyun y = mc3230_convert_to_int(buffer[1]) * g_value;
622*4882a593Smuzhiyun z = mc3230_convert_to_int(buffer[2]) * g_value;
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun axis.x =
625*4882a593Smuzhiyun (pdata->orientation[0]) * x + (pdata->orientation[1]) * y +
626*4882a593Smuzhiyun (pdata->orientation[2]) * z;
627*4882a593Smuzhiyun axis.y =
628*4882a593Smuzhiyun (pdata->orientation[3]) * x + (pdata->orientation[4]) * y +
629*4882a593Smuzhiyun (pdata->orientation[5]) * z;
630*4882a593Smuzhiyun axis.z =
631*4882a593Smuzhiyun (pdata->orientation[6]) * x + (pdata->orientation[7]) * y +
632*4882a593Smuzhiyun (pdata->orientation[8]) * z;
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun /* input dev will ignore report data if data value is the same with last_value,
635*4882a593Smuzhiyun sample rate will not enough by this way, so just avoid this case */
636*4882a593Smuzhiyun if ((sensor->axis.x == axis.x) && (sensor->axis.y == axis.y) && (sensor->axis.z == axis.z)) {
637*4882a593Smuzhiyun if (flag) {
638*4882a593Smuzhiyun flag = 0;
639*4882a593Smuzhiyun axis.x += 1;
640*4882a593Smuzhiyun axis.y += 1;
641*4882a593Smuzhiyun axis.z += 1;
642*4882a593Smuzhiyun } else {
643*4882a593Smuzhiyun flag = 1;
644*4882a593Smuzhiyun axis.x -= 1;
645*4882a593Smuzhiyun axis.y -= 1;
646*4882a593Smuzhiyun axis.z -= 1;
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun }
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun mc3230_report_value(client, &axis);
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun mutex_lock(&sensor->data_mutex);
653*4882a593Smuzhiyun sensor->axis = axis;
654*4882a593Smuzhiyun mutex_unlock(&sensor->data_mutex);
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun return 0;
657*4882a593Smuzhiyun }
658*4882a593Smuzhiyun
MC32X0_ReadRBMData(struct i2c_client * client,char * buf)659*4882a593Smuzhiyun static int MC32X0_ReadRBMData(struct i2c_client *client, char *buf)
660*4882a593Smuzhiyun {
661*4882a593Smuzhiyun struct mc3230_data *mc3230 =
662*4882a593Smuzhiyun (struct mc3230_data *)i2c_get_clientdata(client);
663*4882a593Smuzhiyun int res = 0;
664*4882a593Smuzhiyun int data[3];
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun if (!buf || !client)
667*4882a593Smuzhiyun return -EINVAL;
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun if (mc3230->status == MC3230_CLOSE) {
670*4882a593Smuzhiyun res = mc3230_start(client, 0);
671*4882a593Smuzhiyun if (res)
672*4882a593Smuzhiyun GSE_ERR("Power on mc32x0 error %d!\n", res);
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun res = MC32X0_ReadData_RBM(client, data);
675*4882a593Smuzhiyun if (res) {
676*4882a593Smuzhiyun GSE_ERR("%s I2C error: ret value=%d", __func__, res);
677*4882a593Smuzhiyun return -EIO;
678*4882a593Smuzhiyun } else {
679*4882a593Smuzhiyun sprintf(buf, "%04x %04x %04x", data[MC32X0_AXIS_X],
680*4882a593Smuzhiyun data[MC32X0_AXIS_Y], data[MC32X0_AXIS_Z]);
681*4882a593Smuzhiyun }
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun return 0;
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun
MC32X0_ReadOffset(struct i2c_client * client,s16 ofs[MC32X0_AXES_NUM])686*4882a593Smuzhiyun static int MC32X0_ReadOffset(struct i2c_client *client,
687*4882a593Smuzhiyun s16 ofs[MC32X0_AXES_NUM])
688*4882a593Smuzhiyun {
689*4882a593Smuzhiyun int err;
690*4882a593Smuzhiyun u8 off_data[6];
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun off_data[0] = MC32X0_XOUT_EX_L_REG;
693*4882a593Smuzhiyun if ((mc32x0_type == IS_MC3210) || (mc32x0_type == IS_MC3413)
694*4882a593Smuzhiyun || (mc32x0_type == IS_MC3416)) {
695*4882a593Smuzhiyun err = sensor_rx_data(client, off_data, MC32X0_DATA_LEN);
696*4882a593Smuzhiyun if (err) {
697*4882a593Smuzhiyun GSE_ERR("error: %d\n", err);
698*4882a593Smuzhiyun return err;
699*4882a593Smuzhiyun }
700*4882a593Smuzhiyun ofs[MC32X0_AXIS_X] =
701*4882a593Smuzhiyun ((s16)(off_data[0])) | ((s16)(off_data[1]) << 8);
702*4882a593Smuzhiyun ofs[MC32X0_AXIS_Y] =
703*4882a593Smuzhiyun ((s16)(off_data[2])) | ((s16)(off_data[3]) << 8);
704*4882a593Smuzhiyun ofs[MC32X0_AXIS_Z] =
705*4882a593Smuzhiyun ((s16)(off_data[4])) | ((s16)(off_data[5]) << 8);
706*4882a593Smuzhiyun } else if ((mc32x0_type == IS_MC3230) || (mc32x0_type == IS_MC2234)) {
707*4882a593Smuzhiyun err = sensor_rx_data(client, off_data, MC32X0_DATA_LEN);
708*4882a593Smuzhiyun if (err) {
709*4882a593Smuzhiyun GSE_ERR("error: %d\n", err);
710*4882a593Smuzhiyun return err;
711*4882a593Smuzhiyun }
712*4882a593Smuzhiyun ofs[MC32X0_AXIS_X] = (s8)off_data[0];
713*4882a593Smuzhiyun ofs[MC32X0_AXIS_Y] = (s8)off_data[1];
714*4882a593Smuzhiyun ofs[MC32X0_AXIS_Z] = (s8)off_data[2];
715*4882a593Smuzhiyun }
716*4882a593Smuzhiyun GSE_LOG("MC32X0_ReadOffset %d %d %d \n", ofs[MC32X0_AXIS_X],
717*4882a593Smuzhiyun ofs[MC32X0_AXIS_Y], ofs[MC32X0_AXIS_Z]);
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun return 0;
720*4882a593Smuzhiyun }
721*4882a593Smuzhiyun
MC32X0_ResetCalibration(struct i2c_client * client)722*4882a593Smuzhiyun static int MC32X0_ResetCalibration(struct i2c_client *client)
723*4882a593Smuzhiyun {
724*4882a593Smuzhiyun struct mc3230_data *mc3230 = get_3230_ctl_data();
725*4882a593Smuzhiyun s16 tmp, i;
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun sensor_write_reg(client, 0x07, 0x43);
728*4882a593Smuzhiyun
729*4882a593Smuzhiyun for (i = 0; i < 6; i++) {
730*4882a593Smuzhiyun sensor_write_reg(client, 0x21 + i, offset_buf[i]);
731*4882a593Smuzhiyun msleep(10);
732*4882a593Smuzhiyun }
733*4882a593Smuzhiyun
734*4882a593Smuzhiyun sensor_write_reg(client, 0x07, 0x41);
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun msleep(20);
737*4882a593Smuzhiyun
738*4882a593Smuzhiyun /* add by Liang for set offset_buf as OTP value */
739*4882a593Smuzhiyun tmp = ((offset_buf[1] & 0x3f) << 8) + offset_buf[0];
740*4882a593Smuzhiyun if (tmp & 0x2000)
741*4882a593Smuzhiyun tmp |= 0xc000;
742*4882a593Smuzhiyun offset_data[0] = tmp;
743*4882a593Smuzhiyun
744*4882a593Smuzhiyun tmp = ((offset_buf[3] & 0x3f) << 8) + offset_buf[2];
745*4882a593Smuzhiyun if (tmp & 0x2000)
746*4882a593Smuzhiyun tmp |= 0xc000;
747*4882a593Smuzhiyun offset_data[1] = tmp;
748*4882a593Smuzhiyun
749*4882a593Smuzhiyun tmp = ((offset_buf[5] & 0x3f) << 8) + offset_buf[4];
750*4882a593Smuzhiyun if (tmp & 0x2000)
751*4882a593Smuzhiyun tmp |= 0xc000;
752*4882a593Smuzhiyun offset_data[2] = tmp;
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun memset(mc3230->cali_sw, 0x00, sizeof(mc3230->cali_sw));
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun return 0;
757*4882a593Smuzhiyun }
758*4882a593Smuzhiyun
MC32X0_ReadCalibration(struct i2c_client * client,int dat[MC32X0_AXES_NUM])759*4882a593Smuzhiyun static int MC32X0_ReadCalibration(struct i2c_client *client,
760*4882a593Smuzhiyun int dat[MC32X0_AXES_NUM])
761*4882a593Smuzhiyun {
762*4882a593Smuzhiyun struct mc3230_data *mc3230 = get_3230_ctl_data();
763*4882a593Smuzhiyun int err;
764*4882a593Smuzhiyun
765*4882a593Smuzhiyun err = MC32X0_ReadOffset(client, mc3230->offset);
766*4882a593Smuzhiyun if (err) {
767*4882a593Smuzhiyun GSE_ERR("read offset fail, %d\n", err);
768*4882a593Smuzhiyun return err;
769*4882a593Smuzhiyun }
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun dat[MC32X0_AXIS_X] = mc3230->offset[MC32X0_AXIS_X];
772*4882a593Smuzhiyun dat[MC32X0_AXIS_Y] = mc3230->offset[MC32X0_AXIS_Y];
773*4882a593Smuzhiyun dat[MC32X0_AXIS_Z] = mc3230->offset[MC32X0_AXIS_Z];
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun return 0;
776*4882a593Smuzhiyun }
777*4882a593Smuzhiyun
MC32X0_WriteCalibration(struct i2c_client * client,int dat[MC32X0_AXES_NUM])778*4882a593Smuzhiyun static int MC32X0_WriteCalibration(struct i2c_client *client,
779*4882a593Smuzhiyun int dat[MC32X0_AXES_NUM])
780*4882a593Smuzhiyun {
781*4882a593Smuzhiyun int err;
782*4882a593Smuzhiyun u8 buf[9], i;
783*4882a593Smuzhiyun s16 tmp, x_gain, y_gain, z_gain;
784*4882a593Smuzhiyun s32 x_off, y_off, z_off;
785*4882a593Smuzhiyun
786*4882a593Smuzhiyun GSE_LOG("UPDATE dat: (%+3d %+3d %+3d)\n",
787*4882a593Smuzhiyun dat[MC32X0_AXIS_X], dat[MC32X0_AXIS_Y], dat[MC32X0_AXIS_Z]);
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun /* read register 0x21~0x28 */
790*4882a593Smuzhiyun buf[0] = 0x21;
791*4882a593Smuzhiyun err = sensor_rx_data(client, &buf[0], 3);
792*4882a593Smuzhiyun buf[3] = 0x24;
793*4882a593Smuzhiyun err = sensor_rx_data(client, &buf[3], 3);
794*4882a593Smuzhiyun buf[6] = 0x27;
795*4882a593Smuzhiyun err = sensor_rx_data(client, &buf[6], 3);
796*4882a593Smuzhiyun
797*4882a593Smuzhiyun /* get x,y,z offset */
798*4882a593Smuzhiyun tmp = ((buf[1] & 0x3f) << 8) + buf[0];
799*4882a593Smuzhiyun if (tmp & 0x2000)
800*4882a593Smuzhiyun tmp |= 0xc000;
801*4882a593Smuzhiyun x_off = tmp;
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun tmp = ((buf[3] & 0x3f) << 8) + buf[2];
804*4882a593Smuzhiyun if (tmp & 0x2000)
805*4882a593Smuzhiyun tmp |= 0xc000;
806*4882a593Smuzhiyun y_off = tmp;
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun tmp = ((buf[5] & 0x3f) << 8) + buf[4];
809*4882a593Smuzhiyun if (tmp & 0x2000)
810*4882a593Smuzhiyun tmp |= 0xc000;
811*4882a593Smuzhiyun z_off = tmp;
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun /* get x,y,z gain */
814*4882a593Smuzhiyun x_gain = ((buf[1] >> 7) << 8) + buf[6];
815*4882a593Smuzhiyun y_gain = ((buf[3] >> 7) << 8) + buf[7];
816*4882a593Smuzhiyun z_gain = ((buf[5] >> 7) << 8) + buf[8];
817*4882a593Smuzhiyun
818*4882a593Smuzhiyun /* prepare new offset */
819*4882a593Smuzhiyun x_off =
820*4882a593Smuzhiyun x_off +
821*4882a593Smuzhiyun 16 * dat[MC32X0_AXIS_X] * 256 * 128 / 3 / gsensor_gain.x / (40 +
822*4882a593Smuzhiyun x_gain);
823*4882a593Smuzhiyun y_off =
824*4882a593Smuzhiyun y_off +
825*4882a593Smuzhiyun 16 * dat[MC32X0_AXIS_Y] * 256 * 128 / 3 / gsensor_gain.y / (40 +
826*4882a593Smuzhiyun y_gain);
827*4882a593Smuzhiyun z_off =
828*4882a593Smuzhiyun z_off +
829*4882a593Smuzhiyun 16 * dat[MC32X0_AXIS_Z] * 256 * 128 / 3 / gsensor_gain.z / (40 +
830*4882a593Smuzhiyun z_gain);
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun /* storege the cerrunt offset data with DOT format */
833*4882a593Smuzhiyun offset_data[0] = x_off;
834*4882a593Smuzhiyun offset_data[1] = y_off;
835*4882a593Smuzhiyun offset_data[2] = z_off;
836*4882a593Smuzhiyun
837*4882a593Smuzhiyun /* storege the cerrunt Gain data with GOT format */
838*4882a593Smuzhiyun gain_data[0] = 256 * 8 * 128 / 3 / (40 + x_gain);
839*4882a593Smuzhiyun gain_data[1] = 256 * 8 * 128 / 3 / (40 + y_gain);
840*4882a593Smuzhiyun gain_data[2] = 256 * 8 * 128 / 3 / (40 + z_gain);
841*4882a593Smuzhiyun
842*4882a593Smuzhiyun sensor_write_reg(client, 0x07, 0x43);
843*4882a593Smuzhiyun
844*4882a593Smuzhiyun buf[0] = x_off & 0xff;
845*4882a593Smuzhiyun buf[1] = ((x_off >> 8) & 0x3f) | (x_gain & 0x0100 ? 0x80 : 0);
846*4882a593Smuzhiyun buf[2] = y_off & 0xff;
847*4882a593Smuzhiyun buf[3] = ((y_off >> 8) & 0x3f) | (y_gain & 0x0100 ? 0x80 : 0);
848*4882a593Smuzhiyun buf[4] = z_off & 0xff;
849*4882a593Smuzhiyun buf[5] = ((z_off >> 8) & 0x3f) | (z_gain & 0x0100 ? 0x80 : 0);
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun for (i = 0; i < 6; i++) {
852*4882a593Smuzhiyun sensor_write_reg(client, 0x21 + i, buf[i]);
853*4882a593Smuzhiyun msleep(10);
854*4882a593Smuzhiyun }
855*4882a593Smuzhiyun
856*4882a593Smuzhiyun sensor_write_reg(client, 0x07, 0x41);
857*4882a593Smuzhiyun
858*4882a593Smuzhiyun return err;
859*4882a593Smuzhiyun }
860*4882a593Smuzhiyun
MC32X0_ReadData(struct i2c_client * client,s16 buffer[MC32X0_AXES_NUM])861*4882a593Smuzhiyun static int MC32X0_ReadData(struct i2c_client *client,
862*4882a593Smuzhiyun s16 buffer[MC32X0_AXES_NUM])
863*4882a593Smuzhiyun {
864*4882a593Smuzhiyun s8 buf[3];
865*4882a593Smuzhiyun u8 buf1[6];
866*4882a593Smuzhiyun char rbm_buf[6];
867*4882a593Smuzhiyun int ret;
868*4882a593Smuzhiyun int err = 0;
869*4882a593Smuzhiyun
870*4882a593Smuzhiyun int tempX = 0;
871*4882a593Smuzhiyun int tempY = 0;
872*4882a593Smuzhiyun int tempZ = 0;
873*4882a593Smuzhiyun
874*4882a593Smuzhiyun if (!client) {
875*4882a593Smuzhiyun err = -EINVAL;
876*4882a593Smuzhiyun return err;
877*4882a593Smuzhiyun }
878*4882a593Smuzhiyun mcprintkfunc("MC32X0_ReadData enable_RBM_calibration = %d\n",
879*4882a593Smuzhiyun enable_RBM_calibration);
880*4882a593Smuzhiyun if (enable_RBM_calibration == 0) {
881*4882a593Smuzhiyun ;
882*4882a593Smuzhiyun } else if (enable_RBM_calibration == 1) {
883*4882a593Smuzhiyun memset(rbm_buf, 0, 3);
884*4882a593Smuzhiyun rbm_buf[0] = MC3230_REG_RBM_DATA;
885*4882a593Smuzhiyun ret = sensor_rx_data(client, &rbm_buf[0], 2);
886*4882a593Smuzhiyun rbm_buf[2] = MC3230_REG_RBM_DATA + 2;
887*4882a593Smuzhiyun ret = sensor_rx_data(client, &rbm_buf[2], 2);
888*4882a593Smuzhiyun rbm_buf[4] = MC3230_REG_RBM_DATA + 4;
889*4882a593Smuzhiyun ret = sensor_rx_data(client, &rbm_buf[4], 2);
890*4882a593Smuzhiyun }
891*4882a593Smuzhiyun
892*4882a593Smuzhiyun mcprintkfunc("MC32X0_ReadData %d %d %d %d %d %d\n", rbm_buf[0],
893*4882a593Smuzhiyun rbm_buf[1], rbm_buf[2], rbm_buf[3], rbm_buf[4],
894*4882a593Smuzhiyun rbm_buf[5]);
895*4882a593Smuzhiyun if (enable_RBM_calibration == 0) {
896*4882a593Smuzhiyun do {
897*4882a593Smuzhiyun memset(buf, 0, 3);
898*4882a593Smuzhiyun buf[0] = MC3230_REG_X_OUT;
899*4882a593Smuzhiyun ret = sensor_rx_data(client, &buf[0], 3);
900*4882a593Smuzhiyun if (ret < 0)
901*4882a593Smuzhiyun return ret;
902*4882a593Smuzhiyun } while (0);
903*4882a593Smuzhiyun
904*4882a593Smuzhiyun buffer[0] = (s16)buf[0];
905*4882a593Smuzhiyun buffer[1] = (s16)buf[1];
906*4882a593Smuzhiyun buffer[2] = (s16)buf[2];
907*4882a593Smuzhiyun
908*4882a593Smuzhiyun if (mc32x0_type == IS_MC2234) {
909*4882a593Smuzhiyun tempX = buffer[MC32X0_AXIS_X];
910*4882a593Smuzhiyun tempY = buffer[MC32X0_AXIS_Y];
911*4882a593Smuzhiyun tempZ = buffer[MC32X0_AXIS_Z];
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun buffer[MC32X0_AXIS_Z] =
914*4882a593Smuzhiyun (s8)(gsensor_gain.z - (abs(tempX) + abs(tempY)));
915*4882a593Smuzhiyun }
916*4882a593Smuzhiyun
917*4882a593Smuzhiyun else if ((mc32x0_type == IS_MC3210)
918*4882a593Smuzhiyun || (mc32x0_type == IS_MC3413)
919*4882a593Smuzhiyun || (mc32x0_type == IS_MC3416)) {
920*4882a593Smuzhiyun do {
921*4882a593Smuzhiyun memset(buf1, 0, 6);
922*4882a593Smuzhiyun buf[0] = MC32X0_XOUT_EX_L_REG;
923*4882a593Smuzhiyun
924*4882a593Smuzhiyun buf1[0] =
925*4882a593Smuzhiyun sensor_read_reg(client,
926*4882a593Smuzhiyun MC32X0_XOUT_EX_L_REG);
927*4882a593Smuzhiyun buf1[1] =
928*4882a593Smuzhiyun sensor_read_reg(client,
929*4882a593Smuzhiyun MC32X0_XOUT_EX_L_REG + 1);
930*4882a593Smuzhiyun buf1[2] =
931*4882a593Smuzhiyun sensor_read_reg(client,
932*4882a593Smuzhiyun MC32X0_XOUT_EX_L_REG + 2);
933*4882a593Smuzhiyun buf1[3] =
934*4882a593Smuzhiyun sensor_read_reg(client,
935*4882a593Smuzhiyun MC32X0_XOUT_EX_L_REG + 3);
936*4882a593Smuzhiyun buf1[4] =
937*4882a593Smuzhiyun sensor_read_reg(client,
938*4882a593Smuzhiyun MC32X0_XOUT_EX_L_REG + 4);
939*4882a593Smuzhiyun buf1[5] =
940*4882a593Smuzhiyun sensor_read_reg(client,
941*4882a593Smuzhiyun MC32X0_XOUT_EX_L_REG + 5);
942*4882a593Smuzhiyun } while (0);
943*4882a593Smuzhiyun
944*4882a593Smuzhiyun buffer[0] = (signed short)((buf1[0]) | (buf1[1] << 8));
945*4882a593Smuzhiyun buffer[1] = (signed short)((buf1[2]) | (buf1[3] << 8));
946*4882a593Smuzhiyun buffer[2] = (signed short)((buf1[4]) | (buf1[5] << 8));
947*4882a593Smuzhiyun }
948*4882a593Smuzhiyun
949*4882a593Smuzhiyun } else if (enable_RBM_calibration == 1) {
950*4882a593Smuzhiyun buffer[MC32X0_AXIS_X] =
951*4882a593Smuzhiyun (s16)((rbm_buf[0]) | (rbm_buf[1] << 8));
952*4882a593Smuzhiyun buffer[MC32X0_AXIS_Y] =
953*4882a593Smuzhiyun (s16)((rbm_buf[2]) | (rbm_buf[3] << 8));
954*4882a593Smuzhiyun buffer[MC32X0_AXIS_Z] =
955*4882a593Smuzhiyun (s16)((rbm_buf[4]) | (rbm_buf[5] << 8));
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun mcprintkfunc("%s RBM<<<<<[%08d %08d %08d]\n", __func__,
958*4882a593Smuzhiyun buffer[MC32X0_AXIS_X], buffer[MC32X0_AXIS_Y],
959*4882a593Smuzhiyun buffer[MC32X0_AXIS_Z]);
960*4882a593Smuzhiyun if (gain_data[0] == 0) {
961*4882a593Smuzhiyun buffer[MC32X0_AXIS_X] = 0;
962*4882a593Smuzhiyun buffer[MC32X0_AXIS_Y] = 0;
963*4882a593Smuzhiyun buffer[MC32X0_AXIS_Z] = 0;
964*4882a593Smuzhiyun return 0;
965*4882a593Smuzhiyun }
966*4882a593Smuzhiyun buffer[MC32X0_AXIS_X] =
967*4882a593Smuzhiyun (buffer[MC32X0_AXIS_X] +
968*4882a593Smuzhiyun offset_data[0] / 2) * gsensor_gain.x / gain_data[0];
969*4882a593Smuzhiyun buffer[MC32X0_AXIS_Y] =
970*4882a593Smuzhiyun (buffer[MC32X0_AXIS_Y] +
971*4882a593Smuzhiyun offset_data[1] / 2) * gsensor_gain.y / gain_data[1];
972*4882a593Smuzhiyun buffer[MC32X0_AXIS_Z] =
973*4882a593Smuzhiyun (buffer[MC32X0_AXIS_Z] +
974*4882a593Smuzhiyun offset_data[2] / 2) * gsensor_gain.z / gain_data[2];
975*4882a593Smuzhiyun
976*4882a593Smuzhiyun if (mc32x0_type == IS_MC2234) {
977*4882a593Smuzhiyun tempX = buffer[MC32X0_AXIS_X];
978*4882a593Smuzhiyun tempY = buffer[MC32X0_AXIS_Y];
979*4882a593Smuzhiyun tempZ = buffer[MC32X0_AXIS_Z];
980*4882a593Smuzhiyun
981*4882a593Smuzhiyun buffer[MC32X0_AXIS_Z] =
982*4882a593Smuzhiyun (s16)(gsensor_gain.z - (abs(tempX) + abs(tempY)));
983*4882a593Smuzhiyun }
984*4882a593Smuzhiyun }
985*4882a593Smuzhiyun
986*4882a593Smuzhiyun return 0;
987*4882a593Smuzhiyun }
988*4882a593Smuzhiyun
MC32X0_ReadRawData(struct i2c_client * client,char * buf)989*4882a593Smuzhiyun static int MC32X0_ReadRawData(struct i2c_client *client, char *buf)
990*4882a593Smuzhiyun {
991*4882a593Smuzhiyun struct mc3230_data *obj = get_3230_ctl_data();
992*4882a593Smuzhiyun int res = 0;
993*4882a593Smuzhiyun s16 raw_buf[3];
994*4882a593Smuzhiyun
995*4882a593Smuzhiyun if (!buf || !client)
996*4882a593Smuzhiyun return -EINVAL;
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun if (obj->status == MC3230_CLOSE) {
999*4882a593Smuzhiyun res = mc3230_start(client, 0);
1000*4882a593Smuzhiyun if (res)
1001*4882a593Smuzhiyun GSE_ERR("Power on mc32x0 error %d!\n", res);
1002*4882a593Smuzhiyun }
1003*4882a593Smuzhiyun res = MC32X0_ReadData(client, &raw_buf[0]);
1004*4882a593Smuzhiyun if (res) {
1005*4882a593Smuzhiyun GSE_LOG("%s %d\n", __func__, __LINE__);
1006*4882a593Smuzhiyun GSE_ERR("I2C error: ret value=%d", res);
1007*4882a593Smuzhiyun return -EIO;
1008*4882a593Smuzhiyun } else {
1009*4882a593Smuzhiyun GSE_LOG("UPDATE dat: (%+3d %+3d %+3d)\n",
1010*4882a593Smuzhiyun raw_buf[MC32X0_AXIS_X], raw_buf[MC32X0_AXIS_Y],
1011*4882a593Smuzhiyun raw_buf[MC32X0_AXIS_Z]);
1012*4882a593Smuzhiyun
1013*4882a593Smuzhiyun G_RAW_DATA[MC32X0_AXIS_X] = raw_buf[0];
1014*4882a593Smuzhiyun G_RAW_DATA[MC32X0_AXIS_Y] = raw_buf[1];
1015*4882a593Smuzhiyun G_RAW_DATA[MC32X0_AXIS_Z] = raw_buf[2];
1016*4882a593Smuzhiyun G_RAW_DATA[MC32X0_AXIS_Z] =
1017*4882a593Smuzhiyun G_RAW_DATA[MC32X0_AXIS_Z] + gsensor_gain.z;
1018*4882a593Smuzhiyun
1019*4882a593Smuzhiyun sprintf(buf, "%04x %04x %04x", G_RAW_DATA[MC32X0_AXIS_X],
1020*4882a593Smuzhiyun G_RAW_DATA[MC32X0_AXIS_Y], G_RAW_DATA[MC32X0_AXIS_Z]);
1021*4882a593Smuzhiyun GSE_LOG("G_RAW_DATA: (%+3d %+3d %+3d)\n",
1022*4882a593Smuzhiyun G_RAW_DATA[MC32X0_AXIS_X], G_RAW_DATA[MC32X0_AXIS_Y],
1023*4882a593Smuzhiyun G_RAW_DATA[MC32X0_AXIS_Z]);
1024*4882a593Smuzhiyun }
1025*4882a593Smuzhiyun
1026*4882a593Smuzhiyun return 0;
1027*4882a593Smuzhiyun }
1028*4882a593Smuzhiyun
mcube_copy_file(const char * dstfilepath)1029*4882a593Smuzhiyun static void mcube_copy_file(const char *dstfilepath)
1030*4882a593Smuzhiyun {
1031*4882a593Smuzhiyun int err = 0;
1032*4882a593Smuzhiyun
1033*4882a593Smuzhiyun initKernelEnv();
1034*4882a593Smuzhiyun fd_file = openFile(dstfilepath, O_RDWR, 0);
1035*4882a593Smuzhiyun if (!fd_file) {
1036*4882a593Smuzhiyun GSE_LOG("open %s fail\n", dstfilepath);
1037*4882a593Smuzhiyun return;
1038*4882a593Smuzhiyun }
1039*4882a593Smuzhiyun
1040*4882a593Smuzhiyun err = writeFile(fd_file, backup_buf, 64);
1041*4882a593Smuzhiyun if (err > 0)
1042*4882a593Smuzhiyun GSE_LOG("buf:%s\n", backup_buf);
1043*4882a593Smuzhiyun else
1044*4882a593Smuzhiyun GSE_LOG("write file error %d\n", err);
1045*4882a593Smuzhiyun
1046*4882a593Smuzhiyun set_fs(oldfs);
1047*4882a593Smuzhiyun closeFile(fd_file);
1048*4882a593Smuzhiyun }
1049*4882a593Smuzhiyun
mc3230_ioctl(struct file * file,unsigned int cmd,unsigned long arg,struct i2c_client * client)1050*4882a593Smuzhiyun long mc3230_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
1051*4882a593Smuzhiyun struct i2c_client *client)
1052*4882a593Smuzhiyun {
1053*4882a593Smuzhiyun void __user *argp = (void __user *)arg;
1054*4882a593Smuzhiyun
1055*4882a593Smuzhiyun char strbuf[256];
1056*4882a593Smuzhiyun void __user *data;
1057*4882a593Smuzhiyun SENSOR_DATA sensor_data;
1058*4882a593Smuzhiyun int err = 0;
1059*4882a593Smuzhiyun int cali[3];
1060*4882a593Smuzhiyun
1061*4882a593Smuzhiyun struct mc3230_data *p_mc3230_data = get_3230_ctl_data();
1062*4882a593Smuzhiyun struct sensor_axis sense_data = { 0 };
1063*4882a593Smuzhiyun
1064*4882a593Smuzhiyun mcprintkreg("mc3230_ioctl cmd is %d.", cmd);
1065*4882a593Smuzhiyun
1066*4882a593Smuzhiyun switch (cmd) {
1067*4882a593Smuzhiyun case GSENSOR_IOCTL_READ_SENSORDATA:
1068*4882a593Smuzhiyun case GSENSOR_IOCTL_READ_RAW_DATA:
1069*4882a593Smuzhiyun GSE_LOG("fwq GSENSOR_IOCTL_READ_RAW_DATA\n");
1070*4882a593Smuzhiyun data = (void __user *)arg;
1071*4882a593Smuzhiyun MC32X0_ReadRawData(client, strbuf);
1072*4882a593Smuzhiyun if (copy_to_user(data, &strbuf, strlen(strbuf) + 1)) {
1073*4882a593Smuzhiyun err = -EFAULT;
1074*4882a593Smuzhiyun break;
1075*4882a593Smuzhiyun }
1076*4882a593Smuzhiyun break;
1077*4882a593Smuzhiyun case GSENSOR_IOCTL_SET_CALI:
1078*4882a593Smuzhiyun
1079*4882a593Smuzhiyun GSE_LOG("fwq GSENSOR_IOCTL_SET_CALI!!\n");
1080*4882a593Smuzhiyun
1081*4882a593Smuzhiyun break;
1082*4882a593Smuzhiyun
1083*4882a593Smuzhiyun case GSENSOR_MCUBE_IOCTL_SET_CALI:
1084*4882a593Smuzhiyun GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_SET_CALI!!\n");
1085*4882a593Smuzhiyun data = (void __user *)arg;
1086*4882a593Smuzhiyun if (!data) {
1087*4882a593Smuzhiyun err = -EINVAL;
1088*4882a593Smuzhiyun break;
1089*4882a593Smuzhiyun }
1090*4882a593Smuzhiyun if (copy_from_user(&sensor_data, data, sizeof(sensor_data))) {
1091*4882a593Smuzhiyun err = -EFAULT;
1092*4882a593Smuzhiyun break;
1093*4882a593Smuzhiyun } else {
1094*4882a593Smuzhiyun cali[MC32X0_AXIS_X] = sensor_data.x;
1095*4882a593Smuzhiyun cali[MC32X0_AXIS_Y] = sensor_data.y;
1096*4882a593Smuzhiyun cali[MC32X0_AXIS_Z] = sensor_data.z;
1097*4882a593Smuzhiyun
1098*4882a593Smuzhiyun GSE_LOG
1099*4882a593Smuzhiyun ("MCUBE_IOCTL_SET_CALI %d %d %d %d %d %d!!\n",
1100*4882a593Smuzhiyun cali[MC32X0_AXIS_X], cali[MC32X0_AXIS_Y],
1101*4882a593Smuzhiyun cali[MC32X0_AXIS_Z], sensor_data.x, sensor_data.y,
1102*4882a593Smuzhiyun sensor_data.z);
1103*4882a593Smuzhiyun
1104*4882a593Smuzhiyun err = MC32X0_WriteCalibration(client, cali);
1105*4882a593Smuzhiyun }
1106*4882a593Smuzhiyun break;
1107*4882a593Smuzhiyun case GSENSOR_IOCTL_CLR_CALI:
1108*4882a593Smuzhiyun GSE_LOG("fwq GSENSOR_IOCTL_CLR_CALI!!\n");
1109*4882a593Smuzhiyun err = MC32X0_ResetCalibration(client);
1110*4882a593Smuzhiyun break;
1111*4882a593Smuzhiyun case GSENSOR_IOCTL_GET_CALI:
1112*4882a593Smuzhiyun GSE_LOG("fwq mc32x0 GSENSOR_IOCTL_GET_CALI\n");
1113*4882a593Smuzhiyun data = (void __user *)arg;
1114*4882a593Smuzhiyun if (!data) {
1115*4882a593Smuzhiyun err = -EINVAL;
1116*4882a593Smuzhiyun break;
1117*4882a593Smuzhiyun }
1118*4882a593Smuzhiyun
1119*4882a593Smuzhiyun err = MC32X0_ReadCalibration(client, cali);
1120*4882a593Smuzhiyun if (err) {
1121*4882a593Smuzhiyun GSE_LOG
1122*4882a593Smuzhiyun ("fwq mc32x0 MC32X0_ReadCalibration error!!!!\n");
1123*4882a593Smuzhiyun break;
1124*4882a593Smuzhiyun }
1125*4882a593Smuzhiyun
1126*4882a593Smuzhiyun sensor_data.x = p_mc3230_data->cali_sw[MC32X0_AXIS_X];
1127*4882a593Smuzhiyun sensor_data.y = p_mc3230_data->cali_sw[MC32X0_AXIS_Y];
1128*4882a593Smuzhiyun sensor_data.z = p_mc3230_data->cali_sw[MC32X0_AXIS_Z];
1129*4882a593Smuzhiyun if (copy_to_user(data, &sensor_data, sizeof(sensor_data))) {
1130*4882a593Smuzhiyun err = -EFAULT;
1131*4882a593Smuzhiyun break;
1132*4882a593Smuzhiyun }
1133*4882a593Smuzhiyun break;
1134*4882a593Smuzhiyun case GSENSOR_IOCTL_SET_CALI_MODE:
1135*4882a593Smuzhiyun GSE_LOG("fwq mc32x0 GSENSOR_IOCTL_SET_CALI_MODE\n");
1136*4882a593Smuzhiyun break;
1137*4882a593Smuzhiyun case GSENSOR_MCUBE_IOCTL_READ_RBM_DATA:
1138*4882a593Smuzhiyun GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_READ_RBM_DATA\n");
1139*4882a593Smuzhiyun data = (void __user *)arg;
1140*4882a593Smuzhiyun if (!data) {
1141*4882a593Smuzhiyun err = -EINVAL;
1142*4882a593Smuzhiyun break;
1143*4882a593Smuzhiyun }
1144*4882a593Smuzhiyun MC32X0_ReadRBMData(client, (char *)&strbuf);
1145*4882a593Smuzhiyun if (copy_to_user(data, &strbuf, strlen(strbuf) + 1)) {
1146*4882a593Smuzhiyun err = -EFAULT;
1147*4882a593Smuzhiyun break;
1148*4882a593Smuzhiyun }
1149*4882a593Smuzhiyun break;
1150*4882a593Smuzhiyun case GSENSOR_MCUBE_IOCTL_SET_RBM_MODE:
1151*4882a593Smuzhiyun GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_SET_RBM_MODE\n");
1152*4882a593Smuzhiyun if (READ_FROM_BACKUP == true) {
1153*4882a593Smuzhiyun mcube_copy_file(calib_path);
1154*4882a593Smuzhiyun READ_FROM_BACKUP = false;
1155*4882a593Smuzhiyun }
1156*4882a593Smuzhiyun MC32X0_rbm(client, 1);
1157*4882a593Smuzhiyun break;
1158*4882a593Smuzhiyun case GSENSOR_MCUBE_IOCTL_CLEAR_RBM_MODE:
1159*4882a593Smuzhiyun GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_SET_RBM_MODE\n");
1160*4882a593Smuzhiyun
1161*4882a593Smuzhiyun MC32X0_rbm(client, 0);
1162*4882a593Smuzhiyun break;
1163*4882a593Smuzhiyun case GSENSOR_MCUBE_IOCTL_REGISTER_MAP:
1164*4882a593Smuzhiyun GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_REGISTER_MAP\n");
1165*4882a593Smuzhiyun break;
1166*4882a593Smuzhiyun default:
1167*4882a593Smuzhiyun return -ENOTTY;
1168*4882a593Smuzhiyun }
1169*4882a593Smuzhiyun
1170*4882a593Smuzhiyun switch (cmd) {
1171*4882a593Smuzhiyun case MC_IOCTL_GETDATA:
1172*4882a593Smuzhiyun if (copy_to_user(argp, &sense_data, sizeof(sense_data))) {
1173*4882a593Smuzhiyun GSE_LOG("failed to copy sense data to user space.");
1174*4882a593Smuzhiyun return -EFAULT;
1175*4882a593Smuzhiyun }
1176*4882a593Smuzhiyun break;
1177*4882a593Smuzhiyun case GSENSOR_IOCTL_READ_RAW_DATA:
1178*4882a593Smuzhiyun case GSENSOR_IOCTL_READ_SENSORDATA:
1179*4882a593Smuzhiyun if (copy_to_user(argp, &strbuf, strlen(strbuf) + 1)) {
1180*4882a593Smuzhiyun GSE_LOG("failed to copy sense data to user space.");
1181*4882a593Smuzhiyun return -EFAULT;
1182*4882a593Smuzhiyun }
1183*4882a593Smuzhiyun break;
1184*4882a593Smuzhiyun default:
1185*4882a593Smuzhiyun break;
1186*4882a593Smuzhiyun }
1187*4882a593Smuzhiyun
1188*4882a593Smuzhiyun return 0;
1189*4882a593Smuzhiyun }
1190*4882a593Smuzhiyun
1191*4882a593Smuzhiyun /* odr table, hz */
1192*4882a593Smuzhiyun static const int odr_table[8] = {
1193*4882a593Smuzhiyun 1, 2, 4, 8, 16, 32, 64, 128
1194*4882a593Smuzhiyun };
1195*4882a593Smuzhiyun
mc3230_select_odr(int want)1196*4882a593Smuzhiyun static int mc3230_select_odr(int want)
1197*4882a593Smuzhiyun {
1198*4882a593Smuzhiyun int i;
1199*4882a593Smuzhiyun int max_index = ARRAY_SIZE(odr_table);
1200*4882a593Smuzhiyun
1201*4882a593Smuzhiyun for (i = 0; i < max_index; i++) {
1202*4882a593Smuzhiyun if (want <= odr_table[i])
1203*4882a593Smuzhiyun return max_index - i - 1;
1204*4882a593Smuzhiyun }
1205*4882a593Smuzhiyun
1206*4882a593Smuzhiyun return 0;
1207*4882a593Smuzhiyun }
sensor_active(struct i2c_client * client,int enable,int rate)1208*4882a593Smuzhiyun static int sensor_active(struct i2c_client *client, int enable, int rate)
1209*4882a593Smuzhiyun {
1210*4882a593Smuzhiyun struct sensor_private_data *sensor =
1211*4882a593Smuzhiyun (struct sensor_private_data *)i2c_get_clientdata(client);
1212*4882a593Smuzhiyun int result = 0;
1213*4882a593Smuzhiyun int mc3230_rate = 0;
1214*4882a593Smuzhiyun
1215*4882a593Smuzhiyun if (rate == 0) {
1216*4882a593Smuzhiyun dev_err(&client->dev, "%s: rate == 0!!!\n", __func__);
1217*4882a593Smuzhiyun return -1;
1218*4882a593Smuzhiyun }
1219*4882a593Smuzhiyun
1220*4882a593Smuzhiyun mc3230_rate = mc3230_select_odr(1000 / rate);
1221*4882a593Smuzhiyun
1222*4882a593Smuzhiyun mc3230_rate = 0xf8 | (0x07 & mc3230_rate);
1223*4882a593Smuzhiyun
1224*4882a593Smuzhiyun if (rate != 0xff)
1225*4882a593Smuzhiyun result =
1226*4882a593Smuzhiyun sensor_write_reg(client, MC32X0_Sample_Rate_REG,
1227*4882a593Smuzhiyun mc3230_rate);
1228*4882a593Smuzhiyun if (result) {
1229*4882a593Smuzhiyun pr_info("%s:line=%d,error\n", __func__, __LINE__);
1230*4882a593Smuzhiyun return result;
1231*4882a593Smuzhiyun }
1232*4882a593Smuzhiyun
1233*4882a593Smuzhiyun sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
1234*4882a593Smuzhiyun
1235*4882a593Smuzhiyun if (!enable) {
1236*4882a593Smuzhiyun sensor->ops->ctrl_data &= ~MC3230_MODE_BITS;
1237*4882a593Smuzhiyun sensor->ops->ctrl_data |= MC32X0_MODE_SLEEP;
1238*4882a593Smuzhiyun } else {
1239*4882a593Smuzhiyun sensor->ops->ctrl_data &= ~MC3230_MODE_BITS;
1240*4882a593Smuzhiyun sensor->ops->ctrl_data |= MC32X0_MODE_WAKEUP;
1241*4882a593Smuzhiyun }
1242*4882a593Smuzhiyun
1243*4882a593Smuzhiyun result =
1244*4882a593Smuzhiyun sensor_write_reg(client, sensor->ops->ctrl_reg,
1245*4882a593Smuzhiyun sensor->ops->ctrl_data);
1246*4882a593Smuzhiyun if (result)
1247*4882a593Smuzhiyun GSE_LOG("%s:fail to active sensor\n", __func__);
1248*4882a593Smuzhiyun
1249*4882a593Smuzhiyun return result;
1250*4882a593Smuzhiyun }
1251*4882a593Smuzhiyun
sensor_init(struct i2c_client * client)1252*4882a593Smuzhiyun static int sensor_init(struct i2c_client *client)
1253*4882a593Smuzhiyun {
1254*4882a593Smuzhiyun struct sensor_private_data *sensor =
1255*4882a593Smuzhiyun (struct sensor_private_data *)i2c_get_clientdata(client);
1256*4882a593Smuzhiyun int result = 0;
1257*4882a593Smuzhiyun
1258*4882a593Smuzhiyun if (init_3230_ctl_data(client))
1259*4882a593Smuzhiyun return -1;
1260*4882a593Smuzhiyun
1261*4882a593Smuzhiyun result = sensor->ops->active(client, 0, sensor->pdata->poll_delay_ms);
1262*4882a593Smuzhiyun if (result) {
1263*4882a593Smuzhiyun GSE_LOG("%s:line=%d,error\n", __func__, __LINE__);
1264*4882a593Smuzhiyun return result;
1265*4882a593Smuzhiyun }
1266*4882a593Smuzhiyun
1267*4882a593Smuzhiyun sensor->status_cur = SENSOR_OFF;
1268*4882a593Smuzhiyun
1269*4882a593Smuzhiyun result = sensor_write_reg(client, MC32X0_Interrupt_Enable_REG, 0x10);
1270*4882a593Smuzhiyun if (result) {
1271*4882a593Smuzhiyun GSE_LOG("%s:line=%d,error\n", __func__, __LINE__);
1272*4882a593Smuzhiyun return result;
1273*4882a593Smuzhiyun }
1274*4882a593Smuzhiyun
1275*4882a593Smuzhiyun result = sensor->ops->active(client, 1, 31);
1276*4882a593Smuzhiyun if (result) {
1277*4882a593Smuzhiyun GSE_LOG("%s:line=%d,error\n", __func__, __LINE__);
1278*4882a593Smuzhiyun return result;
1279*4882a593Smuzhiyun }
1280*4882a593Smuzhiyun
1281*4882a593Smuzhiyun return result;
1282*4882a593Smuzhiyun }
1283*4882a593Smuzhiyun
sensor_report_value(struct i2c_client * client)1284*4882a593Smuzhiyun static int sensor_report_value(struct i2c_client *client)
1285*4882a593Smuzhiyun {
1286*4882a593Smuzhiyun int ret = 0;
1287*4882a593Smuzhiyun
1288*4882a593Smuzhiyun mc3230_get_data(client);
1289*4882a593Smuzhiyun
1290*4882a593Smuzhiyun return ret;
1291*4882a593Smuzhiyun }
1292*4882a593Smuzhiyun
1293*4882a593Smuzhiyun static struct sensor_operate gsensor_ops = {
1294*4882a593Smuzhiyun .name = "gs_mc3230",
1295*4882a593Smuzhiyun /*sensor type and it should be correct */
1296*4882a593Smuzhiyun .type = SENSOR_TYPE_ACCEL,
1297*4882a593Smuzhiyun /* i2c id number */
1298*4882a593Smuzhiyun .id_i2c = ACCEL_ID_MC3230,
1299*4882a593Smuzhiyun /* read data */
1300*4882a593Smuzhiyun .read_reg = MC32X0_XOUT_REG,
1301*4882a593Smuzhiyun /* data length */
1302*4882a593Smuzhiyun .read_len = 3,
1303*4882a593Smuzhiyun /* read device id from this register, but mc3230 has no id register */
1304*4882a593Smuzhiyun .id_reg = SENSOR_UNKNOW_DATA,
1305*4882a593Smuzhiyun /* device id */
1306*4882a593Smuzhiyun .id_data = SENSOR_UNKNOW_DATA,
1307*4882a593Smuzhiyun /* 6 bits */
1308*4882a593Smuzhiyun .precision = 6,
1309*4882a593Smuzhiyun /* enable or disable */
1310*4882a593Smuzhiyun .ctrl_reg = MC32X0_Mode_Feature_REG,
1311*4882a593Smuzhiyun /* intterupt status register */
1312*4882a593Smuzhiyun .int_status_reg = MC32X0_Interrupt_Enable_REG,
1313*4882a593Smuzhiyun .range = {-32768, 32768},
1314*4882a593Smuzhiyun .trig = (IRQF_TRIGGER_HIGH | IRQF_ONESHOT),
1315*4882a593Smuzhiyun .active = sensor_active,
1316*4882a593Smuzhiyun .init = sensor_init,
1317*4882a593Smuzhiyun .report = sensor_report_value,
1318*4882a593Smuzhiyun };
1319*4882a593Smuzhiyun
1320*4882a593Smuzhiyun /****************operate according to sensor chip:end************/
gsensor_mc3230_probe(struct i2c_client * client,const struct i2c_device_id * devid)1321*4882a593Smuzhiyun static int gsensor_mc3230_probe(struct i2c_client *client,
1322*4882a593Smuzhiyun const struct i2c_device_id *devid)
1323*4882a593Smuzhiyun {
1324*4882a593Smuzhiyun return sensor_register_device(client, NULL, devid, &gsensor_ops);
1325*4882a593Smuzhiyun }
1326*4882a593Smuzhiyun
gsensor_mc3230_remove(struct i2c_client * client)1327*4882a593Smuzhiyun static int gsensor_mc3230_remove(struct i2c_client *client)
1328*4882a593Smuzhiyun {
1329*4882a593Smuzhiyun return sensor_unregister_device(client, NULL, &gsensor_ops);
1330*4882a593Smuzhiyun }
1331*4882a593Smuzhiyun
1332*4882a593Smuzhiyun static const struct i2c_device_id gsensor_mc3230_id[] = {
1333*4882a593Smuzhiyun {"gs_mc3230", ACCEL_ID_MC3230},
1334*4882a593Smuzhiyun {}
1335*4882a593Smuzhiyun };
1336*4882a593Smuzhiyun
1337*4882a593Smuzhiyun static struct i2c_driver gsensor_mc3230_driver = {
1338*4882a593Smuzhiyun .probe = gsensor_mc3230_probe,
1339*4882a593Smuzhiyun .remove = gsensor_mc3230_remove,
1340*4882a593Smuzhiyun .shutdown = sensor_shutdown,
1341*4882a593Smuzhiyun .id_table = gsensor_mc3230_id,
1342*4882a593Smuzhiyun .driver = {
1343*4882a593Smuzhiyun .name = "gsensor_mc3230",
1344*4882a593Smuzhiyun #ifdef CONFIG_PM
1345*4882a593Smuzhiyun .pm = &sensor_pm_ops,
1346*4882a593Smuzhiyun #endif
1347*4882a593Smuzhiyun },
1348*4882a593Smuzhiyun };
1349*4882a593Smuzhiyun
1350*4882a593Smuzhiyun module_i2c_driver(gsensor_mc3230_driver);
1351*4882a593Smuzhiyun
1352*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1353*4882a593Smuzhiyun MODULE_DESCRIPTION("mc3230 3-Axis accelerometer driver");
1354*4882a593Smuzhiyun MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver);
1355