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