add temperature and pressure sensor driver support
authorluowei <lw@rock-chips.com>
Wed, 27 Feb 2013 02:33:18 +0000 (10:33 +0800)
committerluowei <lw@rock-chips.com>
Wed, 27 Feb 2013 02:33:18 +0000 (10:33 +0800)
drivers/input/sensors/Kconfig
drivers/input/sensors/Makefile
drivers/input/sensors/pressure/Kconfig [new file with mode: 0755]
drivers/input/sensors/pressure/Makefile [new file with mode: 0755]
drivers/input/sensors/pressure/pr_ms5607.c [new file with mode: 0755]
drivers/input/sensors/sensor-dev.c
drivers/input/sensors/temperature/Kconfig
drivers/input/sensors/temperature/Makefile
drivers/input/sensors/temperature/tmp_ms5607.c [new file with mode: 0755]
include/linux/sensor-dev.h

index 25fea663108c728bb7484b81b1ab776e0c87b867..813330bfb3161c823bccf1dd2614344c4995d2c8 100755 (executable)
@@ -15,5 +15,7 @@ source "drivers/input/sensors/gyro/Kconfig"
 source "drivers/input/sensors/lsensor/Kconfig"
 source "drivers/input/sensors/psensor/Kconfig"
 source "drivers/input/sensors/temperature/Kconfig"
+source "drivers/input/sensors/pressure/Kconfig"
+
 
 endif
index 65d9b20b1a4405d697a092762e72bbe8a87b4fa9..1b23c47bea21aa01a930ea8ff2fd1b5396a2324b 100755 (executable)
@@ -4,6 +4,8 @@ obj-$(CONFIG_COMPASS_DEVICE)                    += compass/
 obj-$(CONFIG_GYROSCOPE_DEVICE)                 += gyro/\r
 obj-$(CONFIG_LIGHT_DEVICE)                             += lsensor/\r
 obj-$(CONFIG_PROXIMITY_DEVICE)                 += psensor/\r
+obj-$(CONFIG_TEMPERATURE_DEVICE)               += temperature/\r
+obj-$(CONFIG_PRESSURE_DEVICE)                  += pressure/\r
 \r
 \r
 obj-$(CONFIG_SENSOR_DEVICE)                            += sensor-i2c.o\r
diff --git a/drivers/input/sensors/pressure/Kconfig b/drivers/input/sensors/pressure/Kconfig
new file mode 100755 (executable)
index 0000000..c172f6d
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# pressure sensor drivers configuration
+#
+
+menuconfig PRESSURE_DEVICE
+       bool "pressure sensor device support"
+       default n
+
+if PRESSURE_DEVICE
+ config PR_MS5607
+ bool "pressure sensor ms5607"
+ default n
+endif
diff --git a/drivers/input/sensors/pressure/Makefile b/drivers/input/sensors/pressure/Makefile
new file mode 100755 (executable)
index 0000000..837fafa
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# pressure sensor drivers configuration
+#
+
+obj-$(CONFIG_PR_MS5607)                += pr_ms5607.o
+
diff --git a/drivers/input/sensors/pressure/pr_ms5607.c b/drivers/input/sensors/pressure/pr_ms5607.c
new file mode 100755 (executable)
index 0000000..000f411
--- /dev/null
@@ -0,0 +1,300 @@
+/* drivers/input/sensors/pressure/ms5607.c\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif\r
+#include <linux/sensor-dev.h>\r
+\r
+#if 0\r
+#define SENSOR_DEBUG_TYPE SENSOR_TYPE_PRESSURE\r
+#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+#define CMD_RESET   0x1E  // ADC reset command \r
+#define CMD_ADC_READ 0x00  // ADC read command \r
+#define CMD_ADC_CONV 0x40  // ADC conversion command \r
+#define CMD_ADC_D1   0x00    // ADC D1 conversion \r
+#define CMD_ADC_D2   0x10    // ADC D2 conversion \r
+#define CMD_ADC_256  0x00    // ADC OSR=256 \r
+#define CMD_ADC_512  0x02    // ADC OSR=512 \r
+#define CMD_ADC_1024 0x04    // ADC OSR=1024 \r
+#define CMD_ADC_2048 0x06    // ADC OSR=2048 \r
+#define CMD_ADC_4096 0x08    // ADC OSR=4096 \r
+#define CMD_PROM_RD  0xA0  // Prom read command \r
+\r
+\r
+/****************operate according to sensor chip:start************/\r
+\r
+static int C[8] = {0};\r
+int g_ms5607_temp;\r
+int g_ms5607_pr_status;\r
+\r
+#if defined(CONFIG_TMP_MS5607)\r
+extern int g_ms5607_temp_status;\r
+#else\r
+static int g_ms5607_temp_status = SENSOR_OFF;\r
+#endif\r
+\r
+\r
+static int sensor_active(struct i2c_client *client, int enable, int rate)\r
+{\r
+       int result = 0;\r
+       int i = 0;\r
+       char prom[16];\r
+\r
+       if((enable) && (g_ms5607_temp_status == SENSOR_OFF))\r
+       {\r
+               result = sensor_write_reg_normal(client, CMD_RESET);\r
+               if(result)              \r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+\r
+               //Read PROM (128 bit of calibration words)  \r
+               memset(prom, 0, 16);\r
+               prom[0]= CMD_PROM_RD;//CMD_PROM_RD;   \r
+               for(i=0; i<8; i++)\r
+               {\r
+                       prom[i*2]= CMD_PROM_RD + i*2;\r
+                       result = sensor_rx_data(client, &prom[i*2], 2);\r
+                       if(result)\r
+                       {\r
+                               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+                               return result;\r
+                       }\r
+               }\r
+\r
+               for (i=0;i<8;i++) \r
+               {\r
+                       C[i] = prom[2*i] << 8 | prom[2*i + 1];\r
+                       DBG("prom[%d]=0x%x,prom[%d]=0x%x",2*i,prom[2*i],(2*i + 1),prom[2*i + 1]);\r
+                       DBG("\nC[%d]=%d,",i+1,C[i]);\r
+               } \r
+\r
+       }\r
+       \r
+       g_ms5607_pr_status = enable;\r
+       \r
+       return result;\r
+}\r
+\r
+static int sensor_init(struct i2c_client *client)\r
+{      \r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       \r
+       result = sensor->ops->active(client,0,0);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+       \r
+       sensor->status_cur = SENSOR_OFF;\r
+       g_ms5607_pr_status = sensor->status_cur;\r
+       \r
+       //Reset\r
+       //result = sensor_write_reg_normal(client, CMD_RESET);\r
+       //if(result)            \r
+        //printk("%s:line=%d,error\n",__func__,__LINE__);      \r
+    \r
+       return result;\r
+}\r
+\r
+\r
+static int pressure_report_value(struct input_dev *input, int data)\r
+{\r
+       //get pressure, high and temperature from register data\r
+\r
+       input_report_abs(input, ABS_PRESSURE, data);\r
+       input_sync(input);\r
+       \r
+       return 0;\r
+}\r
+\r
+\r
+static int sensor_report_value(struct i2c_client *client)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+    \r
+       int result = 0;\r
+       char buffer[3]; \r
+       char index = 0;\r
+       unsigned int  D1=0, D2=0;\r
+\r
+       int T2 = 0;\r
+       long long OFF = 0;      // offset at actual temperature \r
+       long long SENS = 0;     // sensitivity at actual temperature \r
+       int dT = 0;             // difference between actual and measured temperature\r
+       long long OFF2 = 0;\r
+       long long SENS2 = 0;\r
+       int P = 0;              // compensated pressure value \r
+\r
+\r
+       memset(buffer, 0, 3);\r
+       if(sensor->ops->read_len < 3)   //sensor->ops->read_len = 3\r
+       {\r
+               printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);\r
+               return -1;\r
+       }\r
+\r
+       //D1 conversion\r
+       sensor_write_reg_normal(client,  CMD_ADC_CONV + CMD_ADC_D1 + CMD_ADC_4096);\r
+       msleep(10);\r
+\r
+       memset(buffer, 0, 3);\r
+       buffer[0] = CMD_ADC_READ;\r
+       result = sensor_rx_data(client, &buffer[0], 3);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+\r
+       D1 = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];\r
+       DBG("\nD1=%d :buffer[0]=0x%x,buffer[1]=0x%x,buffer2]=0x%x\n",D1,buffer[0],buffer[1],buffer[2]);\r
+\r
+       //D2 conversion\r
+       sensor_write_reg_normal(client,  CMD_ADC_CONV + CMD_ADC_D2 + CMD_ADC_4096);\r
+       msleep(10);\r
+\r
+       memset(buffer, 0, 3);\r
+       buffer[0] = CMD_ADC_READ;\r
+       result = sensor_rx_data(client, &buffer[0], 3);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+\r
+       D2 = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];\r
+       DBG("D2=%d:buffer[0]=0x%x,buffer[1]=0x%x,buffer2]=0x%x\n",D2,buffer[0],buffer[1],buffer[2]);\r
+\r
+       dT = D2 - ((unsigned int)C[5] << 8);\r
+\r
+       g_ms5607_temp = (int)(2000 + ((long long)dT * C[6] >> 23));\r
+\r
+       OFF = ((unsigned long long)C[2] << 17) + (C[4] * (long long)dT >> 6);\r
+\r
+       SENS = ((long long)C[1] << 16) + (C[3] * (long long)dT >> 7);\r
+\r
+       /*calcualte 2nd order pressure and temperature (BP5607 2nd order algorithm)*/\r
+       if (g_ms5607_temp < -4000 || g_ms5607_temp > 8500)\r
+       {\r
+               printk("%s:temperature is error\n",__func__);\r
+               return -1;\r
+       }\r
+\r
+       if (g_ms5607_temp < 2000)\r
+       {\r
+               int tmp;\r
+               tmp = (g_ms5607_temp - 2000) * (g_ms5607_temp - 2000);\r
+\r
+               T2 = (int)((long long)(dT * dT) >> 31);\r
+               OFF2 = (((long long)tmp * 61)*((long long)tmp * 61)) >> 4;\r
+               SENS2 = (long long)((tmp*tmp) << 1);\r
+\r
+               if (g_ms5607_temp < -1500)\r
+               {\r
+                       tmp = (g_ms5607_temp + 1500) * (g_ms5607_temp + 1500);\r
+                       OFF2 += 15 * tmp;\r
+                       SENS2 += 8 * tmp;\r
+               }\r
+       }\r
+       else\r
+       {\r
+               T2=0;\r
+               OFF2 = 0;\r
+               SENS2 = 0;\r
+       }\r
+\r
+       g_ms5607_temp -= T2;\r
+       OFF -= OFF2;\r
+       SENS -= SENS2;    \r
+       P = (int)((((D1 * SENS) >> 21) - OFF) >> 15);\r
+\r
+       index = pressure_report_value(sensor->input_dev, P);\r
+\r
+       DBG("%s:pressure=%d,temperature=%d\n",__func__,P,g_ms5607_temp);\r
+       \r
+       return result;\r
+}\r
+\r
+struct sensor_operate pressure_ms5607_ops = {\r
+       .name                           = "pr_ms5607",\r
+       .type                           = SENSOR_TYPE_PRESSURE, //sensor type and it should be correct\r
+       .id_i2c                         = PRESSURE_ID_MS5607,   //i2c id number\r
+       .read_reg                       = SENSOR_UNKNOW_DATA,   //read data\r
+       .read_len                       = 3,                    //data length\r
+       .id_reg                         = SENSOR_UNKNOW_DATA,   //read device id from this register\r
+       .id_data                        = SENSOR_UNKNOW_DATA,   //device id\r
+       .precision                      = 24,                   //8 bits\r
+       .ctrl_reg                       = SENSOR_UNKNOW_DATA,   //enable or disable \r
+       .int_status_reg                 = SENSOR_UNKNOW_DATA,   //intterupt status register\r
+       .range                          = {100,65535},          //range\r
+       .brightness                     = {10,255},             //brightness\r
+       .trig                           = IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,                \r
+       .active                         = sensor_active,        \r
+       .init                           = sensor_init,\r
+       .report                         = sensor_report_value,\r
+};\r
+\r
+/****************operate according to sensor chip:end************/\r
+\r
+//function name should not be changed\r
+static struct sensor_operate *pressure_get_ops(void)\r
+{\r
+       return &pressure_ms5607_ops;\r
+}\r
+\r
+\r
+static int __init pressure_ms5607_init(void)\r
+{\r
+       struct sensor_operate *ops = pressure_get_ops();\r
+       int result = 0;\r
+       int type = ops->type;\r
+       result = sensor_register_slave(type, NULL, NULL, pressure_get_ops);\r
+       printk("%s\n",__func__);\r
+       return result;\r
+}\r
+\r
+static void __exit pressure_ms5607_exit(void)\r
+{\r
+       struct sensor_operate *ops = pressure_get_ops();\r
+       int type = ops->type;\r
+       sensor_unregister_slave(type, NULL, NULL, pressure_get_ops);\r
+}\r
+\r
+\r
+module_init(pressure_ms5607_init);\r
+module_exit(pressure_ms5607_exit);\r
+\r
index 10e43614724dab3bc60eda3727e24d0795ee1769..c172a17c014745998322fd849659c784d6404f7f 100755 (executable)
@@ -43,7 +43,7 @@
 #define DBG(x...)\r
 #endif\r
 \r
-#define SENSOR_VERSION_AND_TIME  "sensor-dev.c v1.0 2013-2-18"\r
+#define SENSOR_VERSION_AND_TIME  "sensor-dev.c v1.1 add pressure and temperature support 2013-2-27"\r
 \r
 \r
 struct sensor_private_data *g_sensor[SENSOR_NUM_TYPES];\r
@@ -306,6 +306,8 @@ static int sensor_irq_init(struct i2c_client *client)
                if((sensor->pdata->type == SENSOR_TYPE_GYROSCOPE) || (sensor->pdata->type == SENSOR_TYPE_ACCEL))\r
                disable_irq_nosync(client->irq);//disable irq\r
                if(((sensor->pdata->type == SENSOR_TYPE_LIGHT) || (sensor->pdata->type == SENSOR_TYPE_PROXIMITY))&& (!(sensor->ops->trig & IRQF_SHARED)))       \r
+               disable_irq_nosync(client->irq);//disable irq   \r
+               if(((sensor->pdata->type == SENSOR_TYPE_TEMPERATURE) || (sensor->pdata->type == SENSOR_TYPE_PRESSURE))&& (!(sensor->ops->trig & IRQF_SHARED)))          \r
                disable_irq_nosync(client->irq);//disable irq\r
                printk("%s:use irq=%d\n",__func__,irq);\r
        }\r
@@ -961,16 +963,186 @@ static int temperature_dev_release(struct inode *inode, struct file *file)
 static long temperature_dev_ioctl(struct file *file,\r
                          unsigned int cmd, unsigned long arg)\r
 {\r
-       //struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_TEMPERATURE];\r
-       //struct i2c_client *client = sensor->client;\r
-       //void __user *argp = (void __user *)arg;\r
+       struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_TEMPERATURE];\r
+       struct i2c_client *client = sensor->client;\r
+       unsigned int *argp = (unsigned int *)arg;       \r
        int result = 0;\r
+\r
+       switch(cmd)\r
+       {\r
+               case TEMPERATURE_IOCTL_GET_ENABLED:\r
+                       *argp = sensor->status_cur;\r
+                       break;\r
+               case TEMPERATURE_IOCTL_ENABLE:          \r
+                       DBG("%s:LIGHTSENSOR_IOCTL_ENABLE start\n", __func__);\r
+                       mutex_lock(&sensor->operation_mutex);    \r
+                       if(*(unsigned int *)argp)\r
+                       {\r
+                               if(sensor->status_cur == SENSOR_OFF)\r
+                               {\r
+                                       if ( (result = sensor->ops->active(client, SENSOR_ON, 0) ) < 0 ) {\r
+                                       mutex_unlock(&sensor->operation_mutex);\r
+                                       printk("%s:fail to active sensor,ret=%d\n",__func__,result);         \r
+                                       goto error;           \r
+                                       }       \r
+                                       if(sensor->pdata->irq_enable)\r
+                                       {\r
+                                               if(!(sensor->ops->trig & IRQF_SHARED))\r
+                                               {\r
+                                                       DBG("%s:enable irq,irq=%d\n",__func__,client->irq);\r
+                                                       enable_irq(client->irq);        //enable irq\r
+                                               }\r
+                                       }       \r
+                                       else\r
+                                       {\r
+                                               PREPARE_DELAYED_WORK(&sensor->delaywork, sensor_delaywork_func);\r
+                                               schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));\r
+                                       }\r
+                                       \r
+                                       sensor->status_cur = SENSOR_ON;\r
+                               }       \r
+                       }\r
+                       else\r
+                       {\r
+                               if(sensor->status_cur == SENSOR_ON)\r
+                               {\r
+                                       if ( (result = sensor->ops->active(client, SENSOR_OFF, 0) ) < 0 ) {\r
+                                       mutex_unlock(&sensor->operation_mutex);              \r
+                                       goto error;\r
+                                       }\r
+                                       \r
+                                       if(sensor->pdata->irq_enable)\r
+                                       {                               \r
+                                               if(!(sensor->ops->trig & IRQF_SHARED))\r
+                                               {\r
+                                                       DBG("%s:disable irq,irq=%d\n",__func__,client->irq);\r
+                                                       disable_irq_nosync(client->irq);//disable irq\r
+                                               }\r
+                                       }\r
+                                       else\r
+                                       cancel_delayed_work_sync(&sensor->delaywork);   \r
+                                       \r
+                                       sensor->status_cur = SENSOR_OFF;\r
+                               }\r
+                       }\r
+                       mutex_unlock(&sensor->operation_mutex);\r
+                       DBG("%s:LIGHTSENSOR_IOCTL_ENABLE OK\n", __func__);\r
+                       break;\r
+               \r
+               default:\r
+                       break;\r
+       }\r
        \r
+error:\r
+       return result;\r
+}\r
+\r
+\r
+static int pressure_dev_open(struct inode *inode, struct file *file)\r
+{\r
+       //struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_PRESSURE];\r
+       //struct i2c_client *client = sensor->client;\r
+\r
+       int result = 0;\r
+\r
 \r
        return result;\r
 }\r
 \r
 \r
+static int pressure_dev_release(struct inode *inode, struct file *file)\r
+{\r
+       //struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_PRESSURE];\r
+       //struct i2c_client *client = sensor->client;\r
+\r
+       int result = 0;\r
+\r
+\r
+       return result;\r
+}\r
+\r
+\r
+/* ioctl - I/O control */\r
+static long pressure_dev_ioctl(struct file *file,\r
+                         unsigned int cmd, unsigned long arg)\r
+{\r
+       struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_PRESSURE];\r
+       struct i2c_client *client = sensor->client;\r
+       unsigned int *argp = (unsigned int *)arg;       \r
+       int result = 0;\r
+\r
+       switch(cmd)\r
+       {\r
+               case PRESSURE_IOCTL_GET_ENABLED:\r
+                       *argp = sensor->status_cur;\r
+                       break;\r
+               case PRESSURE_IOCTL_ENABLE:             \r
+                       DBG("%s:LIGHTSENSOR_IOCTL_ENABLE start\n", __func__);\r
+                       mutex_lock(&sensor->operation_mutex);    \r
+                       if(*(unsigned int *)argp)\r
+                       {\r
+                               if(sensor->status_cur == SENSOR_OFF)\r
+                               {\r
+                                       if ( (result = sensor->ops->active(client, SENSOR_ON, 0) ) < 0 ) {\r
+                                       mutex_unlock(&sensor->operation_mutex);\r
+                                       printk("%s:fail to active sensor,ret=%d\n",__func__,result);         \r
+                                       goto error;           \r
+                                       }       \r
+                                       if(sensor->pdata->irq_enable)\r
+                                       {\r
+                                               if(!(sensor->ops->trig & IRQF_SHARED))\r
+                                               {\r
+                                                       DBG("%s:enable irq,irq=%d\n",__func__,client->irq);\r
+                                                       enable_irq(client->irq);        //enable irq\r
+                                               }\r
+                                       }       \r
+                                       else\r
+                                       {\r
+                                               PREPARE_DELAYED_WORK(&sensor->delaywork, sensor_delaywork_func);\r
+                                               schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));\r
+                                       }\r
+                                       \r
+                                       sensor->status_cur = SENSOR_ON;\r
+                               }       \r
+                       }\r
+                       else\r
+                       {\r
+                               if(sensor->status_cur == SENSOR_ON)\r
+                               {\r
+                                       if ( (result = sensor->ops->active(client, SENSOR_OFF, 0) ) < 0 ) {\r
+                                       mutex_unlock(&sensor->operation_mutex);              \r
+                                       goto error;\r
+                                       }\r
+                                       \r
+                                       if(sensor->pdata->irq_enable)\r
+                                       {                               \r
+                                               if(!(sensor->ops->trig & IRQF_SHARED))\r
+                                               {\r
+                                                       DBG("%s:disable irq,irq=%d\n",__func__,client->irq);\r
+                                                       disable_irq_nosync(client->irq);//disable irq\r
+                                               }\r
+                                       }\r
+                                       else\r
+                                       cancel_delayed_work_sync(&sensor->delaywork);   \r
+                                       \r
+                                       sensor->status_cur = SENSOR_OFF;\r
+                               }\r
+                       }\r
+                       mutex_unlock(&sensor->operation_mutex);\r
+                       DBG("%s:LIGHTSENSOR_IOCTL_ENABLE OK\n", __func__);\r
+                       break;\r
+               \r
+               default:\r
+                       break;\r
+       }\r
+       \r
+error:\r
+       return result;\r
+}\r
+\r
+\r
+\r
+\r
 static int sensor_misc_device_register(struct sensor_private_data *sensor, int type)\r
 {\r
        int result = 0;\r
@@ -1095,6 +1267,26 @@ static int sensor_misc_device_register(struct sensor_private_data *sensor, int t
                                \r
                        break;\r
 \r
+               case SENSOR_TYPE_PRESSURE:\r
+                       if(!sensor->ops->misc_dev)\r
+                       {\r
+                               sensor->fops.owner = THIS_MODULE;\r
+                               sensor->fops.unlocked_ioctl = pressure_dev_ioctl;\r
+                               sensor->fops.open = pressure_dev_open;\r
+                               sensor->fops.release = pressure_dev_release;\r
+\r
+                               sensor->miscdev.minor = MISC_DYNAMIC_MINOR;\r
+                               sensor->miscdev.name = "pressure";\r
+                               sensor->miscdev.fops = &sensor->fops;\r
+                       }       \r
+                       else\r
+                       {\r
+                               memcpy(&sensor->miscdev, sensor->ops->misc_dev, sizeof(*sensor->ops->misc_dev));\r
+\r
+                       }\r
+                               \r
+                       break;\r
+\r
                default:\r
                        printk("%s:unknow sensor type=%d\n",__func__,type);\r
                        result = -1;\r
@@ -1299,6 +1491,11 @@ int sensor_probe(struct i2c_client *client, const struct i2c_device_id *devid)
                        set_bit(EV_ABS, sensor->input_dev->evbit);              \r
                        input_set_abs_params(sensor->input_dev, ABS_THROTTLE, sensor->ops->range[0], sensor->ops->range[1], 0, 0);\r
                        break;\r
+               case SENSOR_TYPE_PRESSURE:                              \r
+                       sensor->input_dev->name = "pressure";\r
+                       set_bit(EV_ABS, sensor->input_dev->evbit);              \r
+                       input_set_abs_params(sensor->input_dev, ABS_PRESSURE, sensor->ops->range[0], sensor->ops->range[1], 0, 0);\r
+                       break;\r
                default:\r
                        printk("%s:unknow sensor type=%d\n",__func__,type);\r
                        break;\r
@@ -1426,8 +1623,15 @@ static const struct i2c_device_id sensor_id[] = {
        {"proximity_al3006", PROXIMITY_ID_AL3006},      \r
        {"ps_stk3171", PROXIMITY_ID_STK3171},\r
        {"ps_ap321xx", PROXIMITY_ID_AP321XX},\r
+       \r
        /*temperature*/\r
-       {"temperature", TEMPERATURE_ID_ALL},\r
+       {"temperature", TEMPERATURE_ID_ALL},    \r
+       {"tmp_ms5607", TEMPERATURE_ID_MS5607},\r
+\r
+       /*pressure*/\r
+       {"pressure", PRESSURE_ID_ALL},\r
+       {"pr_ms5607", PRESSURE_ID_MS5607},\r
+       \r
        {},\r
 };\r
 \r
index 65e61499a54edef83fd9e32459b734acbebad3e2..cbb615b5424f13ce983423bedc9bcebfb4fd402b 100755 (executable)
@@ -1,7 +1,14 @@
 #
-# temperature sensor drivers configuration\r
+# temperature sensor drivers configuration
 #
 
-menuconfig TEMPERATURE_DEVICE\r
-       bool "temperature sensor device support"\r
-       default n       
\ No newline at end of file
+menuconfig TEMPERATURE_DEVICE
+       bool "temperature sensor device support"
+       default n
+
+if TEMPERATURE_DEVICE
+ config TMP_MS5607
+ bool "temperature sensor ms5607"
+ default n
+endif
index 5dba77d01e6486bdaaf1de5a5bba5893ddfcfdfc..2f9f5efaa2f4686a4dea58721a8d1e2aceb965de 100755 (executable)
@@ -1,3 +1,6 @@
 #
-# temperature sensor drivers configuration\r
-#
\ No newline at end of file
+# temperature sensor drivers configuration
+#
+
+obj-$(CONFIG_TMP_MS5607)               += tmp_ms5607.o
+
diff --git a/drivers/input/sensors/temperature/tmp_ms5607.c b/drivers/input/sensors/temperature/tmp_ms5607.c
new file mode 100755 (executable)
index 0000000..8fa5659
--- /dev/null
@@ -0,0 +1,317 @@
+/* drivers/input/sensors/temperature/tmp_ms5607.c\r
+ *\r
+ * Copyright (C) 2012-2015 ROCKCHIP.\r
+ * Author: luowei <lw@rock-chips.com>\r
+ *\r
+ * This software is licensed under the terms of the GNU General Public\r
+ * License version 2, as published by the Free Software Foundation, and\r
+ * may be copied, distributed, and modified under those terms.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ */\r
+#include <linux/interrupt.h>\r
+#include <linux/i2c.h>\r
+#include <linux/slab.h>\r
+#include <linux/irq.h>\r
+#include <linux/miscdevice.h>\r
+#include <linux/gpio.h>\r
+#include <asm/uaccess.h>\r
+#include <asm/atomic.h>\r
+#include <linux/delay.h>\r
+#include <linux/input.h>\r
+#include <linux/workqueue.h>\r
+#include <linux/freezer.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h> \r
+#ifdef CONFIG_HAS_EARLYSUSPEND\r
+#include <linux/earlysuspend.h>\r
+#endif\r
+#include <linux/sensor-dev.h>\r
+\r
+#if 0\r
+#define SENSOR_DEBUG_TYPE SENSOR_TYPE_TEMPERATURE\r
+#define DBG(x...) if(sensor->pdata->type == SENSOR_DEBUG_TYPE) printk(x)\r
+#else\r
+#define DBG(x...)\r
+#endif\r
+\r
+#define CMD_RESET   0x1E  // ADC reset command \r
+#define CMD_ADC_READ 0x00  // ADC read command \r
+#define CMD_ADC_CONV 0x40  // ADC conversion command \r
+#define CMD_ADC_D1   0x00    // ADC D1 conversion \r
+#define CMD_ADC_D2   0x10    // ADC D2 conversion \r
+#define CMD_ADC_256  0x00    // ADC OSR=256 \r
+#define CMD_ADC_512  0x02    // ADC OSR=512 \r
+#define CMD_ADC_1024 0x04    // ADC OSR=1024 \r
+#define CMD_ADC_2048 0x06    // ADC OSR=2048 \r
+#define CMD_ADC_4096 0x08    // ADC OSR=4096 \r
+#define CMD_PROM_RD  0xA0  // Prom read command \r
+\r
+#if defined(CONFIG_PR_MS5607)\r
+extern int g_ms5607_temp;\r
+extern int g_ms5607_pr_status;\r
+#else\r
+static int g_ms5607_temp = 0;\r
+static int g_ms5607_pr_status = SENSOR_OFF;\r
+#endif\r
+\r
+int g_ms5607_temp_status;\r
+static int C[8] = {0};\r
+\r
+/****************operate according to sensor chip:start************/\r
+\r
+static int sensor_active(struct i2c_client *client, int enable, int rate)\r
+{\r
+       int result = 0;\r
+       int i = 0;\r
+       char prom[16];\r
+       \r
+       if((enable)&&(g_ms5607_pr_status == SENSOR_OFF))\r
+       {\r
+               result = sensor_write_reg_normal(client, CMD_RESET);\r
+               if(result)              \r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+\r
+               //Read PROM (128 bit of calibration words)  \r
+               memset(prom, 0, 16);\r
+               prom[0]= CMD_PROM_RD;//CMD_PROM_RD;   \r
+               for(i=0; i<8; i++)\r
+               {\r
+                       prom[i*2]= CMD_PROM_RD + i*2;\r
+                       result = sensor_rx_data(client, &prom[i*2], 2);\r
+                       if(result)\r
+                       {\r
+                               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+                               return result;\r
+                       }\r
+               }\r
+\r
+               for (i=0;i<8;i++) \r
+               {\r
+                       C[i] = prom[2*i] << 8 | prom[2*i + 1];\r
+                       DBG("prom[%d]=0x%x,prom[%d]=0x%x",2*i,prom[2*i],(2*i + 1),prom[2*i + 1]);\r
+                       DBG("\nC[%d]=%d,",i+1,C[i]);\r
+               } \r
+\r
+       }\r
+\r
+       g_ms5607_temp_status = enable;\r
+       \r
+       return result;\r
+}\r
+\r
+\r
+\r
+static int sensor_init(struct i2c_client *client)\r
+{      \r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+       int result = 0;\r
+       \r
+       result = sensor->ops->active(client,0,0);\r
+       if(result)\r
+       {\r
+               printk("%s:line=%d,error\n",__func__,__LINE__);\r
+               return result;\r
+       }\r
+       \r
+       sensor->status_cur = SENSOR_OFF;\r
+       g_ms5607_temp_status = sensor->status_cur;\r
+       //Reset\r
+       //result = sensor_write_reg_normal(client, CMD_RESET);\r
+       //if(result)            \r
+       //printk("%s:line=%d,error\n",__func__,__LINE__); \r
+    \r
+       return result;\r
+}\r
+\r
+\r
+\r
+static int temperature_report_value(struct input_dev *input, int data)\r
+{\r
+       //get temperature, high and temperature from register data\r
+\r
+       input_report_abs(input, ABS_THROTTLE, data);\r
+       input_sync(input);\r
+       \r
+       return 0;\r
+}\r
+\r
+\r
+static int sensor_report_value(struct i2c_client *client)\r
+{\r
+       struct sensor_private_data *sensor =\r
+           (struct sensor_private_data *) i2c_get_clientdata(client);  \r
+    \r
+       int result = 0;\r
+       char buffer[3]; \r
+       char index = 0;\r
+       unsigned int  D1=0, D2=0;\r
+\r
+       int T2 = 0;\r
+       long long OFF = 0;      // offset at actual temperature \r
+       long long SENS = 0;     // sensitivity at actual temperature \r
+       int dT = 0;             // difference between actual and measured temperature\r
+       long long OFF2 = 0;\r
+       long long SENS2 = 0;\r
+       int P = 0;              // compensated pressure value \r
+\r
+\r
+       memset(buffer, 0, 3);\r
+       if(sensor->ops->read_len < 3)   //sensor->ops->read_len = 3\r
+       {\r
+               printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);\r
+               return -1;\r
+       }\r
+\r
+       if(g_ms5607_pr_status ==        SENSOR_OFF)\r
+       {\r
+\r
+               //D1 conversion\r
+               sensor_write_reg_normal(client,  CMD_ADC_CONV + CMD_ADC_D1 + CMD_ADC_4096);\r
+               msleep(10);\r
+\r
+               memset(buffer, 0, 3);\r
+               buffer[0] = CMD_ADC_READ;\r
+               result = sensor_rx_data(client, &buffer[0], 3);\r
+               if(result)\r
+               {\r
+                       printk("%s:line=%d,error\n",__func__,__LINE__);\r
+                       return result;\r
+               }\r
+\r
+               D1 = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];\r
+               DBG("\nD1=%d :buffer[0]=0x%x,buffer[1]=0x%x,buffer2]=0x%x\n",D1,buffer[0],buffer[1],buffer[2]);\r
+\r
+               //D2 conversion\r
+               sensor_write_reg_normal(client,  CMD_ADC_CONV + CMD_ADC_D2 + CMD_ADC_4096);\r
+               msleep(10);\r
+\r
+               memset(buffer, 0, 3);\r
+               buffer[0] = CMD_ADC_READ;\r
+               result = sensor_rx_data(client, &buffer[0], 3);\r
+               if(result)\r
+               {\r
+                       printk("%s:line=%d,error\n",__func__,__LINE__);\r
+                       return result;\r
+               }\r
+\r
+               D2 = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];\r
+               DBG("D2=%d:buffer[0]=0x%x,buffer[1]=0x%x,buffer2]=0x%x\n",D2,buffer[0],buffer[1],buffer[2]);\r
+\r
+               dT = D2 - ((unsigned int)C[5] << 8);\r
+\r
+               g_ms5607_temp = (int)(2000 + ((long long)dT * C[6] >> 23));\r
+\r
+               OFF = ((unsigned long long)C[2] << 17) + (C[4] * (long long)dT >> 6);\r
+\r
+               SENS = ((long long)C[1] << 16) + (C[3] * (long long)dT >> 7);\r
+\r
+               /*calcualte 2nd order pressure and temperature (BP5607 2nd order algorithm)*/\r
+               if (g_ms5607_temp < -4000 || g_ms5607_temp > 8500)\r
+               {\r
+                       printk("%s:temperature is error\n",__func__);\r
+                       return -1;\r
+               }\r
+\r
+               if (g_ms5607_temp < 2000)\r
+               {\r
+                       int tmp;\r
+                       tmp = (g_ms5607_temp - 2000) * (g_ms5607_temp - 2000);\r
+\r
+                       T2 = (int)((long long)(dT * dT) >> 31);\r
+                       OFF2 = (((long long)tmp * 61)*((long long)tmp * 61)) >> 4;\r
+                       SENS2 = (long long)((tmp*tmp) << 1);\r
+\r
+                       if (g_ms5607_temp < -1500)\r
+                       {\r
+                               tmp = (g_ms5607_temp + 1500) * (g_ms5607_temp + 1500);\r
+                               OFF2 += 15 * tmp;\r
+                               SENS2 += 8 * tmp;\r
+                       }\r
+               }\r
+               else\r
+               {\r
+                       T2=0;\r
+                       OFF2 = 0;\r
+                       SENS2 = 0;\r
+               }\r
+\r
+               g_ms5607_temp -= T2;\r
+               OFF -= OFF2;\r
+               SENS -= SENS2;    \r
+               P = (int)((((D1 * SENS) >> 21) - OFF) >> 15);\r
+\r
+               index = temperature_report_value(sensor->input_dev, g_ms5607_temp);\r
+               \r
+               DBG("%s:pressure=%d,temperature=%d\n",__func__,P,g_ms5607_temp);\r
+       \r
+       }\r
+       else\r
+       {       \r
+               index = temperature_report_value(sensor->input_dev, g_ms5607_temp);\r
+               \r
+               #if defined(CONFIG_PR_MS5607)\r
+               DBG("%s:pressure=%d,temperature=%d\n",__func__,P,g_ms5607_temp);\r
+               #else   \r
+               printk("%s:errror,need pr_ms5607\n",__func__);\r
+               #endif\r
+       }\r
+       \r
+       \r
+       return result;\r
+}\r
+\r
+\r
+struct sensor_operate temperature_ms5607_ops = {\r
+       .name                           = "tmp_ms5607",\r
+       .type                           = SENSOR_TYPE_TEMPERATURE,      //sensor type and it should be correct\r
+       .id_i2c                         = TEMPERATURE_ID_MS5607,        //i2c id number\r
+       .read_reg                       = SENSOR_UNKNOW_DATA,   //read data\r
+       .read_len                       = 3,                    //data length\r
+       .id_reg                         = SENSOR_UNKNOW_DATA,   //read device id from this register\r
+       .id_data                        = SENSOR_UNKNOW_DATA,   //device id\r
+       .precision                      = 24,                   //8 bits\r
+       .ctrl_reg                       = SENSOR_UNKNOW_DATA,   //enable or disable \r
+       .int_status_reg                 = SENSOR_UNKNOW_DATA,   //intterupt status register\r
+       .range                          = {100,65535},          //range\r
+       .trig                           = IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,                \r
+       .active                         = sensor_active,        \r
+       .init                           = sensor_init,\r
+       .report                         = sensor_report_value,\r
+};\r
+\r
+/****************operate according to sensor chip:end************/\r
+\r
+//function name should not be changed\r
+static struct sensor_operate *temperature_get_ops(void)\r
+{\r
+       return &temperature_ms5607_ops;\r
+}\r
+\r
+\r
+static int __init temperature_ms5607_init(void)\r
+{\r
+       struct sensor_operate *ops = temperature_get_ops();\r
+       int result = 0;\r
+       int type = ops->type;\r
+       result = sensor_register_slave(type, NULL, NULL, temperature_get_ops);\r
+       DBG("%s\n",__func__);\r
+       return result;\r
+}\r
+\r
+static void __exit temperature_ms5607_exit(void)\r
+{\r
+       struct sensor_operate *ops = temperature_get_ops();\r
+       int type = ops->type;\r
+       sensor_unregister_slave(type, NULL, NULL, temperature_get_ops);\r
+}\r
+\r
+\r
+module_init(temperature_ms5607_init);\r
+module_exit(temperature_ms5607_exit);\r
+\r
index 24c568e2d3c84d9f3811d9ae45eb1ee167096eab..980069ae7f23c5b1b6aed83975dcaf57cc34ed4f 100755 (executable)
@@ -32,7 +32,7 @@ enum sensor_type {
        SENSOR_TYPE_LIGHT,      \r
        SENSOR_TYPE_PROXIMITY,\r
        SENSOR_TYPE_TEMPERATURE,        \r
-       //SENSOR_TYPE_PRESSURE,\r
+       SENSOR_TYPE_PRESSURE,\r
        SENSOR_NUM_TYPES\r
 };\r
 \r
@@ -87,10 +87,13 @@ enum sensor_id {
        PROXIMITY_ID_AL3006,\r
        PROXIMITY_ID_STK3171,\r
        PROXIMITY_ID_AP321XX,\r
-       TEMPERATURE_ID_ALL,\r
+       \r
+       TEMPERATURE_ID_ALL,     \r
+       TEMPERATURE_ID_MS5607,\r
 \r
        PRESSURE_ID_ALL,\r
        PRESSURE_ID_BMA085,\r
+       PRESSURE_ID_MS5607,\r
        SENSOR_NUM_ID,\r
 };\r
 \r
@@ -190,6 +193,18 @@ extern int sensor_unregister_slave(int type,struct i2c_client *client,
 #define PSENSOR_IOCTL_DISABLE                  _IOW(PSENSOR_IOCTL_MAGIC, 3, int *)\r
 \r
 \r
+#define PRESSURE_IOCTL_MAGIC 'r'\r
+#define PRESSURE_IOCTL_GET_ENABLED             _IOR(PRESSURE_IOCTL_MAGIC, 1, int *)\r
+#define PRESSURE_IOCTL_ENABLE                  _IOW(PRESSURE_IOCTL_MAGIC, 2, int *)\r
+#define PRESSURE_IOCTL_DISABLE                 _IOW(PRESSURE_IOCTL_MAGIC, 3, int *)\r
+#define PRESSURE_IOCTL_SET_DELAY                       _IOW(PRESSURE_IOCTL_MAGIC, 4, int *)\r
+\r
+\r
+#define TEMPERATURE_IOCTL_MAGIC 't'\r
+#define TEMPERATURE_IOCTL_GET_ENABLED          _IOR(TEMPERATURE_IOCTL_MAGIC, 1, int *)\r
+#define TEMPERATURE_IOCTL_ENABLE               _IOW(TEMPERATURE_IOCTL_MAGIC, 2, int *)\r
+#define TEMPERATURE_IOCTL_DISABLE              _IOW(TEMPERATURE_IOCTL_MAGIC, 3, int *)\r
+#define TEMPERATURE_IOCTL_SET_DELAY            _IOW(TEMPERATURE_IOCTL_MAGIC, 4, int *)\r
 \r
 \r
 extern int sensor_rx_data(struct i2c_client *client, char *rxData, int length);\r