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