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
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
--- /dev/null
+#
+# 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
--- /dev/null
+#
+# pressure sensor drivers configuration
+#
+
+obj-$(CONFIG_PR_MS5607) += pr_ms5607.o
+
--- /dev/null
+/* 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
#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
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
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
\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
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
{"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
#
-# 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
#
-# temperature sensor drivers configuration\r
-#
\ No newline at end of file
+# temperature sensor drivers configuration
+#
+
+obj-$(CONFIG_TMP_MS5607) += tmp_ms5607.o
+
--- /dev/null
+/* 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
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
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
#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