Merge branch linux-linaro-lsk-v3.10-android
[firefly-linux-kernel-4.4.55.git] / drivers / input / sensors / temperature / tmp_ms5607.c
1 /* drivers/input/sensors/temperature/tmp_ms5607.c\r
2  *\r
3  * Copyright (C) 2012-2015 ROCKCHIP.\r
4  * Author: luowei <lw@rock-chips.com>\r
5  *\r
6  * This software is licensed under the terms of the GNU General Public\r
7  * License version 2, as published by the Free Software Foundation, and\r
8  * may be copied, distributed, and modified under those terms.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  */\r
16 #include <linux/interrupt.h>\r
17 #include <linux/i2c.h>\r
18 #include <linux/slab.h>\r
19 #include <linux/irq.h>\r
20 #include <linux/miscdevice.h>\r
21 #include <linux/gpio.h>\r
22 #include <asm/uaccess.h>\r
23 #include <asm/atomic.h>\r
24 #include <linux/delay.h>\r
25 #include <linux/input.h>\r
26 #include <linux/workqueue.h>\r
27 #include <linux/freezer.h>\r
28 #include <linux/of_gpio.h>\r
29 #ifdef CONFIG_HAS_EARLYSUSPEND\r
30 #include <linux/earlysuspend.h>\r
31 #endif\r
32 #include <linux/sensor-dev.h>\r
33 \r
34 \r
35 #define CMD_RESET   0x1E  // ADC reset command \r
36 #define CMD_ADC_READ 0x00  // ADC read command \r
37 #define CMD_ADC_CONV 0x40  // ADC conversion command \r
38 #define CMD_ADC_D1   0x00    // ADC D1 conversion \r
39 #define CMD_ADC_D2   0x10    // ADC D2 conversion \r
40 #define CMD_ADC_256  0x00    // ADC OSR=256 \r
41 #define CMD_ADC_512  0x02    // ADC OSR=512 \r
42 #define CMD_ADC_1024 0x04    // ADC OSR=1024 \r
43 #define CMD_ADC_2048 0x06    // ADC OSR=2048 \r
44 #define CMD_ADC_4096 0x08    // ADC OSR=4096 \r
45 #define CMD_PROM_RD  0xA0  // Prom read command \r
46 \r
47 #if defined(CONFIG_PR_MS5607)\r
48 extern int g_ms5607_temp;\r
49 extern int g_ms5607_pr_status;\r
50 #else\r
51 static int g_ms5607_temp = 0;\r
52 static int g_ms5607_pr_status = SENSOR_OFF;\r
53 #endif\r
54 \r
55 int g_ms5607_temp_status;\r
56 static int C[8] = {0};\r
57 \r
58 /****************operate according to sensor chip:start************/\r
59 \r
60 static int sensor_active(struct i2c_client *client, int enable, int rate)\r
61 {\r
62         int result = 0;\r
63         int i = 0;\r
64         char prom[16];\r
65         \r
66         if((enable)&&(g_ms5607_pr_status == SENSOR_OFF))\r
67         {\r
68                 result = sensor_write_reg_normal(client, CMD_RESET);\r
69                 if(result)              \r
70                 printk("%s:line=%d,error\n",__func__,__LINE__);\r
71 \r
72                 //Read PROM (128 bit of calibration words)  \r
73                 memset(prom, 0, 16);\r
74                 prom[0]= CMD_PROM_RD;//CMD_PROM_RD;   \r
75                 for(i=0; i<8; i++)\r
76                 {\r
77                         prom[i*2]= CMD_PROM_RD + i*2;\r
78                         result = sensor_rx_data(client, &prom[i*2], 2);\r
79                         if(result)\r
80                         {\r
81                                 printk("%s:line=%d,error\n",__func__,__LINE__);\r
82                                 return result;\r
83                         }\r
84                 }\r
85 \r
86                 for (i=0;i<8;i++) \r
87                 {\r
88                         C[i] = prom[2*i] << 8 | prom[2*i + 1];\r
89                         //printk("prom[%d]=0x%x,prom[%d]=0x%x",2*i,prom[2*i],(2*i + 1),prom[2*i + 1]);\r
90                         //printk("\nC[%d]=%d,",i+1,C[i]);\r
91                 } \r
92 \r
93         }\r
94 \r
95         g_ms5607_temp_status = enable;\r
96         \r
97         return result;\r
98 }\r
99 \r
100 \r
101 \r
102 static int sensor_init(struct i2c_client *client)\r
103 {       \r
104         struct sensor_private_data *sensor =\r
105             (struct sensor_private_data *) i2c_get_clientdata(client);  \r
106         int result = 0;\r
107         \r
108         result = sensor->ops->active(client,0,0);\r
109         if(result)\r
110         {\r
111                 printk("%s:line=%d,error\n",__func__,__LINE__);\r
112                 return result;\r
113         }\r
114         \r
115         sensor->status_cur = SENSOR_OFF;\r
116         g_ms5607_temp_status = sensor->status_cur;\r
117         //Reset\r
118         //result = sensor_write_reg_normal(client, CMD_RESET);\r
119         //if(result)            \r
120         //printk("%s:line=%d,error\n",__func__,__LINE__); \r
121     \r
122         return result;\r
123 }\r
124 \r
125 \r
126 \r
127 static int temperature_report_value(struct input_dev *input, int data)\r
128 {\r
129         //get temperature, high and temperature from register data\r
130 \r
131         input_report_abs(input, ABS_THROTTLE, data);\r
132         input_sync(input);\r
133         \r
134         return 0;\r
135 }\r
136 \r
137 \r
138 static int sensor_report_value(struct i2c_client *client)\r
139 {\r
140         struct sensor_private_data *sensor =\r
141             (struct sensor_private_data *) i2c_get_clientdata(client);  \r
142     \r
143         int result = 0;\r
144         char buffer[3]; \r
145         char index = 0;\r
146         unsigned int  D1=0, D2=0;\r
147 \r
148         int T2 = 0;\r
149         long long OFF = 0;      // offset at actual temperature \r
150         long long SENS = 0;     // sensitivity at actual temperature \r
151         int dT = 0;             // difference between actual and measured temperature\r
152         long long OFF2 = 0;\r
153         long long SENS2 = 0;\r
154         int P = 0;              // compensated pressure value \r
155 \r
156 \r
157         memset(buffer, 0, 3);\r
158         if(sensor->ops->read_len < 3)   //sensor->ops->read_len = 3\r
159         {\r
160                 printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);\r
161                 return -1;\r
162         }\r
163 \r
164         if(g_ms5607_pr_status ==        SENSOR_OFF)\r
165         {\r
166 \r
167                 //D1 conversion\r
168                 sensor_write_reg_normal(client,  CMD_ADC_CONV + CMD_ADC_D1 + CMD_ADC_4096);\r
169                 msleep(10);\r
170 \r
171                 memset(buffer, 0, 3);\r
172                 buffer[0] = CMD_ADC_READ;\r
173                 result = sensor_rx_data(client, &buffer[0], 3);\r
174                 if(result)\r
175                 {\r
176                         printk("%s:line=%d,error\n",__func__,__LINE__);\r
177                         return result;\r
178                 }\r
179 \r
180                 D1 = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];\r
181                 DBG("\nD1=%d :buffer[0]=0x%x,buffer[1]=0x%x,buffer2]=0x%x\n",D1,buffer[0],buffer[1],buffer[2]);\r
182 \r
183                 //D2 conversion\r
184                 sensor_write_reg_normal(client,  CMD_ADC_CONV + CMD_ADC_D2 + CMD_ADC_4096);\r
185                 msleep(10);\r
186 \r
187                 memset(buffer, 0, 3);\r
188                 buffer[0] = CMD_ADC_READ;\r
189                 result = sensor_rx_data(client, &buffer[0], 3);\r
190                 if(result)\r
191                 {\r
192                         printk("%s:line=%d,error\n",__func__,__LINE__);\r
193                         return result;\r
194                 }\r
195 \r
196                 D2 = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];\r
197                 DBG("D2=%d:buffer[0]=0x%x,buffer[1]=0x%x,buffer2]=0x%x\n",D2,buffer[0],buffer[1],buffer[2]);\r
198 \r
199                 dT = D2 - ((unsigned int)C[5] << 8);\r
200 \r
201                 g_ms5607_temp = (int)(2000 + ((long long)dT * C[6] >> 23));\r
202 \r
203                 OFF = ((unsigned long long)C[2] << 17) + (C[4] * (long long)dT >> 6);\r
204 \r
205                 SENS = ((long long)C[1] << 16) + (C[3] * (long long)dT >> 7);\r
206 \r
207                 /*calcualte 2nd order pressure and temperature (BP5607 2nd order algorithm)*/\r
208                 if (g_ms5607_temp < -4000 || g_ms5607_temp > 8500)\r
209                 {\r
210                         printk("%s:temperature is error\n",__func__);\r
211                         return -1;\r
212                 }\r
213 \r
214                 if (g_ms5607_temp < 2000)\r
215                 {\r
216                         int tmp;\r
217                         tmp = (g_ms5607_temp - 2000) * (g_ms5607_temp - 2000);\r
218 \r
219                         T2 = (int)((long long)(dT * dT) >> 31);\r
220                         OFF2 = (((long long)tmp * 61)*((long long)tmp * 61)) >> 4;\r
221                         SENS2 = (long long)((tmp*tmp) << 1);\r
222 \r
223                         if (g_ms5607_temp < -1500)\r
224                         {\r
225                                 tmp = (g_ms5607_temp + 1500) * (g_ms5607_temp + 1500);\r
226                                 OFF2 += 15 * tmp;\r
227                                 SENS2 += 8 * tmp;\r
228                         }\r
229                 }\r
230                 else\r
231                 {\r
232                         T2=0;\r
233                         OFF2 = 0;\r
234                         SENS2 = 0;\r
235                 }\r
236 \r
237                 g_ms5607_temp -= T2;\r
238                 OFF -= OFF2;\r
239                 SENS -= SENS2;    \r
240                 P = (int)((((D1 * SENS) >> 21) - OFF) >> 15);\r
241 \r
242                 index = temperature_report_value(sensor->input_dev, g_ms5607_temp);\r
243                 \r
244                 DBG("%s:pressure=%d,temperature=%d\n",__func__,P,g_ms5607_temp);\r
245         \r
246         }\r
247         else\r
248         {       \r
249                 index = temperature_report_value(sensor->input_dev, g_ms5607_temp);\r
250                 \r
251                 #if defined(CONFIG_PR_MS5607)\r
252                 DBG("%s:pressure=%d,temperature=%d\n",__func__,P,g_ms5607_temp);\r
253                 #else   \r
254                 printk("%s:errror,need pr_ms5607\n",__func__);\r
255                 #endif\r
256         }\r
257         \r
258         \r
259         return result;\r
260 }\r
261 \r
262 \r
263 struct sensor_operate temperature_ms5607_ops = {\r
264         .name                           = "tmp_ms5607",\r
265         .type                           = SENSOR_TYPE_TEMPERATURE,      //sensor type and it should be correct\r
266         .id_i2c                         = TEMPERATURE_ID_MS5607,        //i2c id number\r
267         .read_reg                       = SENSOR_UNKNOW_DATA,   //read data\r
268         .read_len                       = 3,                    //data length\r
269         .id_reg                         = SENSOR_UNKNOW_DATA,   //read device id from this register\r
270         .id_data                        = SENSOR_UNKNOW_DATA,   //device id\r
271         .precision                      = 24,                   //8 bits\r
272         .ctrl_reg                       = SENSOR_UNKNOW_DATA,   //enable or disable \r
273         .int_status_reg                 = SENSOR_UNKNOW_DATA,   //intterupt status register\r
274         .range                          = {100,65535},          //range\r
275         .trig                           = IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,                \r
276         .active                         = sensor_active,        \r
277         .init                           = sensor_init,\r
278         .report                         = sensor_report_value,\r
279 };\r
280 \r
281 /****************operate according to sensor chip:end************/\r
282 \r
283 //function name should not be changed\r
284 static struct sensor_operate *temperature_get_ops(void)\r
285 {\r
286         return &temperature_ms5607_ops;\r
287 }\r
288 \r
289 \r
290 static int __init temperature_ms5607_init(void)\r
291 {\r
292         struct sensor_operate *ops = temperature_get_ops();\r
293         int result = 0;\r
294         int type = ops->type;\r
295         result = sensor_register_slave(type, NULL, NULL, temperature_get_ops);\r
296         return result;\r
297 }\r
298 \r
299 static void __exit temperature_ms5607_exit(void)\r
300 {\r
301         struct sensor_operate *ops = temperature_get_ops();\r
302         int type = ops->type;\r
303         sensor_unregister_slave(type, NULL, NULL, temperature_get_ops);\r
304 }\r
305 \r
306 \r
307 module_init(temperature_ms5607_init);\r
308 module_exit(temperature_ms5607_exit);\r
309 \r