aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sensorhub/stm/factory
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sensorhub/stm/factory')
-rwxr-xr-xdrivers/sensorhub/stm/factory/accel_mpu6500.c311
-rwxr-xr-xdrivers/sensorhub/stm/factory/gesture_max88920.c147
-rwxr-xr-xdrivers/sensorhub/stm/factory/gyro_mpu6500.c674
-rwxr-xr-xdrivers/sensorhub/stm/factory/light_cm3320.c77
-rwxr-xr-xdrivers/sensorhub/stm/factory/magnetic_yas532.c456
-rwxr-xr-xdrivers/sensorhub/stm/factory/mcu_atuc128l5har.c282
-rwxr-xr-xdrivers/sensorhub/stm/factory/mcu_stm32f401.c282
-rwxr-xr-xdrivers/sensorhub/stm/factory/pressure_bmp182.c197
-rwxr-xr-xdrivers/sensorhub/stm/factory/prox_max88920.c457
-rwxr-xr-xdrivers/sensorhub/stm/factory/temphumidity_shtc1.c291
10 files changed, 3174 insertions, 0 deletions
diff --git a/drivers/sensorhub/stm/factory/accel_mpu6500.c b/drivers/sensorhub/stm/factory/accel_mpu6500.c
new file mode 100755
index 0000000..b5deb51
--- /dev/null
+++ b/drivers/sensorhub/stm/factory/accel_mpu6500.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2012, Samsung Electronics Co. Ltd. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "../ssp.h"
+
+/*************************************************************************/
+/* factory Sysfs */
+/*************************************************************************/
+
+#define VENDOR "INVENSENSE"
+#define CHIP_ID "MPU6500"
+
+#define CALIBRATION_FILE_PATH "/efs/calibration_data"
+#define CALIBRATION_DATA_AMOUNT 20
+
+static ssize_t accel_vendor_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", VENDOR);
+}
+
+static ssize_t accel_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", CHIP_ID);
+}
+
+int accel_open_calibration(struct ssp_data *data)
+{
+ int iRet = 0;
+ mm_segment_t old_fs;
+ struct file *cal_filp = NULL;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ cal_filp = filp_open(CALIBRATION_FILE_PATH, O_RDONLY, 0666);
+ if (IS_ERR(cal_filp)) {
+ set_fs(old_fs);
+ iRet = PTR_ERR(cal_filp);
+
+ data->accelcal.x = 0;
+ data->accelcal.y = 0;
+ data->accelcal.z = 0;
+
+ return iRet;
+ }
+
+ iRet = cal_filp->f_op->read(cal_filp, (char *)&data->accelcal,
+ 3 * sizeof(int), &cal_filp->f_pos);
+ if (iRet != 3 * sizeof(int))
+ iRet = -EIO;
+
+ filp_close(cal_filp, current->files);
+ set_fs(old_fs);
+
+ ssp_dbg("[SSP]: open accel calibration %d, %d, %d\n",
+ data->accelcal.x, data->accelcal.y, data->accelcal.z);
+
+ if ((data->accelcal.x == 0) && (data->accelcal.y == 0)
+ && (data->accelcal.z == 0))
+ return ERROR;
+
+ return iRet;
+}
+
+static int enable_accel_for_cal(struct ssp_data *data)
+{
+ u8 uBuf[2] = {0, 10};
+
+ if (atomic_read(&data->aSensorEnable) & (1 << ACCELEROMETER_SENSOR)) {
+ if (get_msdelay(data->adDelayBuf[ACCELEROMETER_SENSOR]) != 10) {
+ send_instruction(data, CHANGE_DELAY,
+ ACCELEROMETER_SENSOR, uBuf, 2);
+ return SUCCESS;
+ }
+ } else {
+ send_instruction(data, ADD_SENSOR,
+ ACCELEROMETER_SENSOR, uBuf, 2);
+ }
+
+ return FAIL;
+}
+
+static void disable_accel_for_cal(struct ssp_data *data, int iDelayChanged)
+{
+ u8 uBuf[2] = {0, 10};
+
+ if (atomic_read(&data->aSensorEnable) & (1 << ACCELEROMETER_SENSOR)) {
+ uBuf[1] = get_msdelay(data->adDelayBuf[ACCELEROMETER_SENSOR]);
+ uBuf[0] = get_delay_cmd(uBuf[1]);
+ if (iDelayChanged)
+ send_instruction(data, CHANGE_DELAY,
+ ACCELEROMETER_SENSOR, uBuf, 2);
+ } else {
+ send_instruction(data, REMOVE_SENSOR,
+ ACCELEROMETER_SENSOR, uBuf, 2);
+ }
+}
+
+static int accel_do_calibrate(struct ssp_data *data, int iEnable)
+{
+ int iSum[3] = { 0, };
+ int iRet = 0, iCount;
+ struct file *cal_filp = NULL;
+ mm_segment_t old_fs;
+
+ if (iEnable) {
+ data->accelcal.x = 0;
+ data->accelcal.y = 0;
+ data->accelcal.z = 0;
+
+ iRet = enable_accel_for_cal(data);
+ msleep(300);
+
+ for (iCount = 0; iCount < CALIBRATION_DATA_AMOUNT; iCount++) {
+ iSum[0] += data->buf[ACCELEROMETER_SENSOR].x;
+ iSum[1] += data->buf[ACCELEROMETER_SENSOR].y;
+ iSum[2] += data->buf[ACCELEROMETER_SENSOR].z;
+ mdelay(10);
+ }
+ disable_accel_for_cal(data, iRet);
+
+ data->accelcal.x = (iSum[0] / CALIBRATION_DATA_AMOUNT);
+ data->accelcal.y = (iSum[1] / CALIBRATION_DATA_AMOUNT);
+ data->accelcal.z = (iSum[2] / CALIBRATION_DATA_AMOUNT);
+
+ if (data->accelcal.z > 0)
+ data->accelcal.z -= MAX_ACCEL_1G;
+ else if (data->accelcal.z < 0)
+ data->accelcal.z += MAX_ACCEL_1G;
+ } else {
+ data->accelcal.x = 0;
+ data->accelcal.y = 0;
+ data->accelcal.z = 0;
+ }
+
+ ssp_dbg("[SSP]: do accel calibrate %d, %d, %d\n",
+ data->accelcal.x, data->accelcal.y, data->accelcal.z);
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ cal_filp = filp_open(CALIBRATION_FILE_PATH,
+ O_CREAT | O_TRUNC | O_WRONLY, 0666);
+ if (IS_ERR(cal_filp)) {
+ pr_err("[SSP]: %s - Can't open calibration file\n", __func__);
+ set_fs(old_fs);
+ iRet = PTR_ERR(cal_filp);
+ return iRet;
+ }
+
+ iRet = cal_filp->f_op->write(cal_filp, (char *)&data->accelcal,
+ 3 * sizeof(int), &cal_filp->f_pos);
+ if (iRet != 3 * sizeof(int)) {
+ pr_err("[SSP]: %s - Can't write the accelcal to file\n",
+ __func__);
+ iRet = -EIO;
+ }
+
+ filp_close(cal_filp, current->files);
+ set_fs(old_fs);
+
+ return iRet;
+}
+
+static ssize_t accel_calibration_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int iRet;
+ int iCount = 0;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ iRet = accel_open_calibration(data);
+ if (iRet < 0)
+ pr_err("[SSP]: %s - calibration open failed(%d)\n", __func__, iRet);
+
+ ssp_dbg("[SSP] Cal data : %d %d %d - %d\n",
+ data->accelcal.x, data->accelcal.y, data->accelcal.z, iRet);
+
+ iCount = sprintf(buf, "%d %d %d %d\n", iRet, data->accelcal.x,
+ data->accelcal.y, data->accelcal.z);
+ return iCount;
+}
+
+static ssize_t accel_calibration_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ int iRet;
+ int64_t dEnable;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ iRet = kstrtoll(buf, 10, &dEnable);
+ if (iRet < 0)
+ return iRet;
+
+ iRet = accel_do_calibrate(data, (int)dEnable);
+ if (iRet < 0)
+ pr_err("[SSP]: %s - accel_do_calibrate() failed\n", __func__);
+
+ return size;
+}
+
+static ssize_t raw_data_read(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n",
+ data->buf[ACCELEROMETER_SENSOR].x,
+ data->buf[ACCELEROMETER_SENSOR].y,
+ data->buf[ACCELEROMETER_SENSOR].z);
+}
+
+static ssize_t accel_reactive_alert_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ char chTempBuf[2] = {0, 10};
+ int iRet, iDelayCnt = 0;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ if (sysfs_streq(buf, "1"))
+ ssp_dbg("[SSP]: %s - on\n", __func__);
+ else if (sysfs_streq(buf, "0"))
+ ssp_dbg("[SSP]: %s - off\n", __func__);
+ else if (sysfs_streq(buf, "2")) {
+ ssp_dbg("[SSP]: %s - factory\n", __func__);
+
+ data->uFactorydataReady = 0;
+ memset(data->uFactorydata, 0, sizeof(char) * FACTORY_DATA_MAX);
+
+ data->bAccelAlert = false;
+ iRet = send_instruction(data, FACTORY_MODE,
+ ACCELEROMETER_FACTORY, chTempBuf, 2);
+
+ while (!(data->uFactorydataReady & (1 << ACCELEROMETER_FACTORY))
+ && (iDelayCnt++ < 150)
+ && (iRet == SUCCESS))
+ msleep(20);
+
+ if ((iDelayCnt >= 150) || (iRet != SUCCESS)) {
+ pr_err("[SSP]: %s - accel Selftest Timeout!!\n",
+ __func__);
+ goto exit;
+ }
+
+ mdelay(5);
+
+ data->bAccelAlert = data->uFactorydata[0];
+ ssp_dbg("[SSP]: %s factory test success!\n", __func__);
+ } else {
+ pr_err("[SSP]: %s - invalid value %d\n", __func__, *buf);
+ return -EINVAL;
+ }
+exit:
+ return size;
+}
+
+static ssize_t accel_reactive_alert_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ bool bSuccess = false;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ if (data->bAccelAlert == true)
+ bSuccess = true;
+ else
+ bSuccess = false;
+
+ data->bAccelAlert = false;
+ return sprintf(buf, "%u\n", bSuccess);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, accel_name_show, NULL);
+static DEVICE_ATTR(vendor, S_IRUGO, accel_vendor_show, NULL);
+static DEVICE_ATTR(calibration, S_IRUGO | S_IWUSR | S_IWGRP,
+ accel_calibration_show, accel_calibration_store);
+static DEVICE_ATTR(raw_data, S_IRUGO, raw_data_read, NULL);
+static DEVICE_ATTR(reactive_alert, S_IRUGO | S_IWUSR | S_IWGRP,
+ accel_reactive_alert_show, accel_reactive_alert_store);
+
+static struct device_attribute *acc_attrs[] = {
+ &dev_attr_name,
+ &dev_attr_vendor,
+ &dev_attr_calibration,
+ &dev_attr_raw_data,
+ &dev_attr_reactive_alert,
+ NULL,
+};
+
+void initialize_accel_factorytest(struct ssp_data *data)
+{
+ sensors_register(data->acc_device, data, acc_attrs,
+ "accelerometer_sensor");
+}
+
+void remove_accel_factorytest(struct ssp_data *data)
+{
+ sensors_unregister(data->acc_device, acc_attrs);
+}
diff --git a/drivers/sensorhub/stm/factory/gesture_max88920.c b/drivers/sensorhub/stm/factory/gesture_max88920.c
new file mode 100755
index 0000000..5205c35
--- /dev/null
+++ b/drivers/sensorhub/stm/factory/gesture_max88920.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2012, Samsung Electronics Co. Ltd. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "../ssp.h"
+
+#define VENDOR "MAXIM"
+#define CHIP_ID "MAX88920"
+
+static ssize_t gestrue_vendor_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", VENDOR);
+}
+
+static ssize_t gestrue_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", CHIP_ID);
+}
+
+static ssize_t raw_data_read(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d\n",
+ data->buf[GESTURE_SENSOR].data[0],
+ data->buf[GESTURE_SENSOR].data[1],
+ data->buf[GESTURE_SENSOR].data[2],
+ data->buf[GESTURE_SENSOR].data[3]);
+}
+
+static ssize_t gesture_get_selftest_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ s16 raw_A = 0, raw_B = 0, raw_C = 0, raw_D = 0;
+ int iDelayCnt = 0, iRet = 0;
+ char chTempBuf[2] = { 0, 10 };
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ iDelayCnt = 0;
+ data->uFactorydataReady = 0;
+ memset(data->uFactorydata, 0, sizeof(char) * FACTORY_DATA_MAX);
+
+ iRet = send_instruction(data, FACTORY_MODE, GESTURE_FACTORY,
+ chTempBuf, 2);
+
+ while (!(data->uFactorydataReady & (1 << GESTURE_FACTORY))
+ && (iDelayCnt++ < 100)
+ && (iRet == SUCCESS))
+ msleep(20);
+
+ if ((iDelayCnt >= 100) || (iRet != SUCCESS)) {
+ pr_err("[SSP]: %s - Gesture Selftest Timeout!!\n", __func__);
+ goto exit;
+ }
+
+ raw_A = data->uFactorydata[0];
+ raw_B = data->uFactorydata[1];
+ raw_C = data->uFactorydata[2];
+ raw_D = data->uFactorydata[3];
+
+ pr_info("[SSP] %s: self test A = %d, B = %d, C = %d, D = %d\n",
+ __func__, raw_A, raw_B, raw_C, raw_D);
+
+exit:
+ return sprintf(buf, "%d,%d,%d,%d\n",
+ raw_A, raw_B, raw_C, raw_D);
+}
+
+static ssize_t ir_current_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ ssp_dbg("[SSP]: %s - Ir_Current Setting = %d\n",
+ __func__, data->uIr_Current);
+
+ return sprintf(buf, "%d\n", data->uIr_Current);
+}
+
+static ssize_t ir_current_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ u16 uNewIrCurrent = DEFUALT_IR_CURRENT;
+ int iRet = 0;
+ u16 current_index = 0;
+ struct ssp_data *data = dev_get_drvdata(dev);
+ static u16 set_current[2][16] = { {0, 25, 50, 75, 100, 125, 150, 175, 225, 250, 275, 300, 325, 350, 375, 400},
+ {2, 28, 34, 50, 66, 82, 98, 114, 130, 146, 162, 178, 194, 210, 226, 242} };
+
+ iRet = kstrtou16(buf, 10, &uNewIrCurrent);
+ if (iRet < 0)
+ pr_err("[SSP]: %s - kstrtoint failed.(%d)\n", __func__, iRet);
+ else {
+ for(current_index = 0; current_index < 16; current_index++) {
+ if (set_current[0][current_index] == uNewIrCurrent) {
+ data->uIr_Current = set_current[1][current_index];
+ }
+ }
+ set_gesture_current(data, data->uIr_Current);
+ data->uIr_Current = uNewIrCurrent;
+ }
+
+ ssp_dbg("[SSP]: %s - new Ir_Current Setting : %d\n",
+ __func__, data->uIr_Current);
+
+ return size;
+}
+
+static DEVICE_ATTR(vendor, S_IRUGO, gestrue_vendor_show, NULL);
+static DEVICE_ATTR(name, S_IRUGO, gestrue_name_show, NULL);
+static DEVICE_ATTR(raw_data, S_IRUGO, raw_data_read, NULL);
+static DEVICE_ATTR(selftest, S_IRUGO, gesture_get_selftest_show, NULL);
+static DEVICE_ATTR(ir_current, S_IRUGO | S_IWUSR | S_IWGRP,
+ ir_current_show, ir_current_store);
+
+static struct device_attribute *gesture_attrs[] = {
+ &dev_attr_vendor,
+ &dev_attr_name,
+ &dev_attr_raw_data,
+ &dev_attr_selftest,
+ &dev_attr_ir_current,
+ NULL,
+};
+
+void initialize_gesture_factorytest(struct ssp_data *data)
+{
+ sensors_register(data->ges_device, data,
+ gesture_attrs, "gesture_sensor");
+}
+
+void remove_gesture_factorytest(struct ssp_data *data)
+{
+ sensors_unregister(data->ges_device, gesture_attrs);
+}
diff --git a/drivers/sensorhub/stm/factory/gyro_mpu6500.c b/drivers/sensorhub/stm/factory/gyro_mpu6500.c
new file mode 100755
index 0000000..ea0391e
--- /dev/null
+++ b/drivers/sensorhub/stm/factory/gyro_mpu6500.c
@@ -0,0 +1,674 @@
+/*
+ * Copyright (C) 2012, Samsung Electronics Co. Ltd. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/kernel.h>
+#include "../ssp.h"
+
+/*************************************************************************/
+/* factory Sysfs */
+/*************************************************************************/
+
+#define VENDOR "INVENSENSE"
+#define CHIP_ID "MPU6500"
+
+#define CALIBRATION_FILE_PATH "/efs/gyro_cal_data"
+#define VERBOSE_OUT 1
+#define CALIBRATION_DATA_AMOUNT 20
+#define DEF_GYRO_FULLSCALE 2000
+#define DEF_GYRO_SENS (32768 / DEF_GYRO_FULLSCALE)
+#define DEF_BIAS_LSB_THRESH_SELF (20 * DEF_GYRO_SENS)
+#define DEF_BIAS_LSB_THRESH_SELF_6500 (30 * DEF_GYRO_SENS)
+#define DEF_RMS_LSB_TH_SELF (5 * DEF_GYRO_SENS)
+#define DEF_RMS_THRESH ((DEF_RMS_LSB_TH_SELF) * (DEF_RMS_LSB_TH_SELF))
+#define DEF_SCALE_FOR_FLOAT (1000)
+#define DEF_RMS_SCALE_FOR_RMS (10000)
+#define DEF_SQRT_SCALE_FOR_RMS (100)
+
+static ssize_t gyro_vendor_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", VENDOR);
+}
+
+static ssize_t gyro_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", CHIP_ID);
+}
+
+int gyro_open_calibration(struct ssp_data *data)
+{
+ int iRet = 0;
+ mm_segment_t old_fs;
+ struct file *cal_filp = NULL;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ cal_filp = filp_open(CALIBRATION_FILE_PATH, O_RDONLY, 0666);
+ if (IS_ERR(cal_filp)) {
+ set_fs(old_fs);
+ iRet = PTR_ERR(cal_filp);
+
+ data->gyrocal.x = 0;
+ data->gyrocal.y = 0;
+ data->gyrocal.z = 0;
+
+ return iRet;
+ }
+
+ iRet = cal_filp->f_op->read(cal_filp, (char *)&data->gyrocal,
+ 3 * sizeof(int), &cal_filp->f_pos);
+ if (iRet != 3 * sizeof(int))
+ iRet = -EIO;
+
+ filp_close(cal_filp, current->files);
+ set_fs(old_fs);
+
+ ssp_dbg("[SSP]: open gyro calibration %d, %d, %d\n",
+ data->gyrocal.x, data->gyrocal.y, data->gyrocal.z);
+ return iRet;
+}
+
+static int save_gyro_caldata(struct ssp_data *data, s16 *iCalData)
+{
+ int iRet = 0;
+ struct file *cal_filp = NULL;
+ mm_segment_t old_fs;
+
+ data->gyrocal.x = iCalData[0];
+ data->gyrocal.y = iCalData[1];
+ data->gyrocal.z = iCalData[2];
+
+ ssp_dbg("[SSP]: do gyro calibrate %d, %d, %d\n",
+ data->gyrocal.x, data->gyrocal.y, data->gyrocal.z);
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ cal_filp = filp_open(CALIBRATION_FILE_PATH,
+ O_CREAT | O_TRUNC | O_WRONLY, 0666);
+ if (IS_ERR(cal_filp)) {
+ pr_err("[SSP]: %s - Can't open calibration file\n", __func__);
+ set_fs(old_fs);
+ iRet = PTR_ERR(cal_filp);
+ return -EIO;
+ }
+
+ iRet = cal_filp->f_op->write(cal_filp, (char *)&data->gyrocal,
+ 3 * sizeof(int), &cal_filp->f_pos);
+ if (iRet != 3 * sizeof(int)) {
+ pr_err("[SSP]: %s - Can't write gyro cal to file\n", __func__);
+ iRet = -EIO;
+ }
+
+ filp_close(cal_filp, current->files);
+ set_fs(old_fs);
+
+ return iRet;
+}
+
+static ssize_t gyro_power_off(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssp_dbg("[SSP]: %s\n", __func__);
+
+ return sprintf(buf, "%d\n", 1);
+}
+
+static ssize_t gyro_power_on(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssp_dbg("[SSP]: %s\n", __func__);
+
+ return sprintf(buf, "%d\n", 1);
+}
+
+short mpu6500_gyro_get_temp(struct ssp_data *data)
+{
+ char chTempBuf[2] = { 0, 10};
+ unsigned char reg[2];
+ short temperature = 0;
+ int iDelayCnt = 0, iRet = 0;
+
+ data->uFactorydataReady = 0;
+ memset(data->uFactorydata, 0, sizeof(char) * FACTORY_DATA_MAX);
+
+ iRet = send_instruction(data, FACTORY_MODE, GYROSCOPE_TEMP_FACTORY,
+ chTempBuf, 2);
+
+ while (!(data->uFactorydataReady & (1 << GYROSCOPE_TEMP_FACTORY))
+ && (iDelayCnt++ < 150)
+ && (iRet == SUCCESS))
+ msleep(20);
+
+ if ((iDelayCnt >= 150) || (iRet != SUCCESS)) {
+ pr_err("[SSP]: %s - Gyro Temp Timeout!!\n", __func__);
+ goto exit;
+ }
+ reg[0] = data->uFactorydata[1];
+ reg[1] = data->uFactorydata[0];
+ temperature = (short) (((reg[0]) << 8) | reg[1]);
+ temperature = (((temperature + 521) / 340) + 35);
+ ssp_dbg("[SSP]: %s - %d\n", __func__, temperature);
+exit:
+ return temperature;
+}
+
+char k330_gyro_get_temp(struct ssp_data *data)
+{
+ char chTempBuf[2] = { 0, 10}, chTemp = 0;
+ int iDelayCnt = 0, iRet = 0;
+
+ if (!(data->uSensorState & (1 << GYROSCOPE_SENSOR)))
+ goto exit;
+
+ data->uFactorydataReady = 0;
+ memset(data->uFactorydata, 0, sizeof(char) * FACTORY_DATA_MAX);
+
+ iRet = send_instruction(data, FACTORY_MODE, GYROSCOPE_TEMP_FACTORY,
+ chTempBuf, 2);
+
+ while (!(data->uFactorydataReady & (1 << GYROSCOPE_TEMP_FACTORY))
+ && (iDelayCnt++ < 150)
+ && (iRet == SUCCESS))
+ msleep(20);
+
+ if ((iDelayCnt >= 150) || (iRet != SUCCESS)) {
+ pr_err("[SSP]: %s - Gyro Temp Timeout!!\n", __func__);
+ goto exit;
+ }
+
+ mdelay(5);
+
+ chTemp = (char)data->uFactorydata[0];
+ ssp_dbg("[SSP]: %s - %d\n", __func__, chTemp);
+exit:
+ return chTemp;
+}
+
+static ssize_t gyro_get_temp(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ short temperature = 0;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ temperature = mpu6500_gyro_get_temp(data);
+
+ return sprintf(buf, "%d\n", temperature);
+}
+
+u32 mpu6050_selftest_sqrt(u32 sqsum)
+{
+ u32 sq_rt;
+ u32 g0, g1, g2, g3, g4;
+ u32 seed;
+ u32 next;
+ u32 step;
+
+ g4 = sqsum / 100000000;
+ g3 = (sqsum - g4 * 100000000) / 1000000;
+ g2 = (sqsum - g4 * 100000000 - g3 * 1000000) / 10000;
+ g1 = (sqsum - g4 * 100000000 - g3 * 1000000 - g2 * 10000) / 100;
+ g0 = (sqsum - g4 * 100000000 - g3 * 1000000 - g2 * 10000 - g1 * 100);
+
+ next = g4;
+ step = 0;
+ seed = 0;
+ while (((seed + 1) * (step + 1)) <= next) {
+ step++;
+ seed++;
+ }
+
+ sq_rt = seed * 10000;
+ next = (next - (seed * step)) * 100 + g3;
+
+ step = 0;
+ seed = 2 * seed * 10;
+ while (((seed + 1) * (step + 1)) <= next) {
+ step++;
+ seed++;
+ }
+
+ sq_rt = sq_rt + step * 1000;
+ next = (next - seed * step) * 100 + g2;
+ seed = (seed + step) * 10;
+ step = 0;
+ while (((seed + 1) * (step + 1)) <= next) {
+ step++;
+ seed++;
+ }
+
+ sq_rt = sq_rt + step * 100;
+ next = (next - seed * step) * 100 + g1;
+ seed = (seed + step) * 10;
+ step = 0;
+
+ while (((seed + 1) * (step + 1)) <= next) {
+ step++;
+ seed++;
+ }
+
+ sq_rt = sq_rt + step * 10;
+ next = (next - seed * step) * 100 + g0;
+ seed = (seed + step) * 10;
+ step = 0;
+
+ while (((seed + 1) * (step + 1)) <= next) {
+ step++;
+ seed++;
+ }
+
+ sq_rt = sq_rt + step;
+
+ return sq_rt;
+}
+
+ssize_t k330_gyro_selftest(char *buf, struct ssp_data *data)
+{
+ char chTempBuf[2] = { 3, 200};
+ u8 uFifoPass = 2;
+ u8 uBypassPass = 2;
+ u8 uCalPass = 0;
+ u8 dummy[2] = {0,};
+ s16 iNOST[3] = {0,}, iST[3] = {0,}, iCalData[3] = {0,};
+ s16 iZeroRateData[3] = {0,}, fifo_data[4] = {0,};
+ int iDelayCnt = 0, iRet = 0;
+
+ data->uFactorydataReady = 0;
+ memset(data->uFactorydata, 0, sizeof(char) * FACTORY_DATA_MAX);
+
+ iRet = send_instruction(data, FACTORY_MODE, GYROSCOPE_FACTORY,
+ chTempBuf, 2);
+
+ while (!(data->uFactorydataReady & (1 << GYROSCOPE_FACTORY))
+ && (iDelayCnt++ < 250)
+ && (iRet == SUCCESS))
+ msleep(20);
+
+ if ((iDelayCnt >= 250) || (iRet != SUCCESS)) {
+ pr_err("[SSP]: %s - Gyro Selftest Timeout!!\n", __func__);
+ goto exit;
+ }
+ mdelay(5);
+
+ iNOST[0] = (s16)((data->uFactorydata[0] << 8) + data->uFactorydata[1]);
+ iNOST[1] = (s16)((data->uFactorydata[2] << 8) + data->uFactorydata[3]);
+ iNOST[2] = (s16)((data->uFactorydata[4] << 8) + data->uFactorydata[5]);
+
+ iST[0] = (s16)((data->uFactorydata[6] << 8) + data->uFactorydata[7]);
+ iST[1] = (s16)((data->uFactorydata[8] << 8) + data->uFactorydata[9]);
+ iST[2] = (s16)((data->uFactorydata[10] << 8) + data->uFactorydata[11]);
+
+ iCalData[0] =
+ (s16)((data->uFactorydata[12] << 8) + data->uFactorydata[13]);
+ iCalData[1] =
+ (s16)((data->uFactorydata[14] << 8) + data->uFactorydata[15]);
+ iCalData[2] =
+ (s16)((data->uFactorydata[16] << 8) + data->uFactorydata[17]);
+
+ iZeroRateData[0] =
+ (s16)((data->uFactorydata[18] << 8) + data->uFactorydata[19]);
+ iZeroRateData[1] =
+ (s16)((data->uFactorydata[20] << 8) + data->uFactorydata[21]);
+ iZeroRateData[2] =
+ (s16)((data->uFactorydata[22] << 8) + data->uFactorydata[23]);
+
+ fifo_data[0] = data->uFactorydata[24];
+ fifo_data[1] =
+ (s16)((data->uFactorydata[25] << 8) + data->uFactorydata[26]);
+ fifo_data[2] =
+ (s16)((data->uFactorydata[27] << 8) + data->uFactorydata[28]);
+ fifo_data[3] =
+ (s16)((data->uFactorydata[29] << 8) + data->uFactorydata[30]);
+
+ uCalPass = data->uFactorydata[31];
+ uFifoPass = data->uFactorydata[32];
+ uBypassPass = data->uFactorydata[33];
+ dummy[0] = data->uFactorydata[34];
+ dummy[1] = data->uFactorydata[35];
+ pr_info("[SSP] %s dummy = 0x%X, 0x%X\n", __func__, dummy[0], dummy[1]);
+ if (uFifoPass && uBypassPass && uCalPass)
+ save_gyro_caldata(data, iCalData);
+
+exit:
+ ssp_dbg("[SSP]: %s - %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
+ __func__, iNOST[0], iNOST[1], iNOST[2], iST[0], iST[1], iST[2],
+ iZeroRateData[0], iZeroRateData[1], iZeroRateData[2],
+ fifo_data[0], fifo_data[1], fifo_data[2], fifo_data[3],
+ uFifoPass & uBypassPass & uCalPass, uFifoPass, uCalPass);
+
+ return sprintf(buf, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
+ iNOST[0], iNOST[1], iNOST[2], iST[0], iST[1], iST[2],
+ iZeroRateData[0], iZeroRateData[1], iZeroRateData[2],
+ fifo_data[0], fifo_data[1], fifo_data[2], fifo_data[3],
+ uFifoPass & uBypassPass & uCalPass, uFifoPass, uCalPass);
+}
+
+ssize_t mpu6500_gyro_selftest(char *buf, struct ssp_data *data)
+{
+ char chTempBuf[2] = { 3, 200};
+ u8 initialized = 0;
+ s8 hw_result = 0;
+ int i = 0, j = 0, total_count = 0, ret_val = 0;
+ long avg[3] = {0,}, rms[3] = {0,};
+ int gyro_bias[3] = {0,}, gyro_rms[3] = {0,};
+ s16 shift_ratio[3] = {0,};
+ s16 iCalData[3] = {0,};
+ char a_name[3][2] = { "X", "Y", "Z" };
+ int iDelayCnt = 0, iRet = 0;
+ int dps_rms[3] = { 0, };
+ u32 temp = 0;
+ int bias_thresh = DEF_BIAS_LSB_THRESH_SELF_6500;
+
+ data->uFactorydataReady = 0;
+ memset(data->uFactorydata, 0, sizeof(char) * FACTORY_DATA_MAX);
+
+ iRet = send_instruction(data, FACTORY_MODE, GYROSCOPE_FACTORY,
+ chTempBuf, 2);
+
+ while (!(data->uFactorydataReady & (1 << GYROSCOPE_FACTORY))
+ && (iDelayCnt++ < 150)
+ && (iRet == SUCCESS))
+ msleep(20);
+
+ if ((iDelayCnt >= 150) || (iRet != SUCCESS)) {
+ pr_err("[SSP]: %s - Gyro Selftest Timeout!!\n", __func__);
+ goto exit;
+ }
+
+ initialized = data->uFactorydata[0];
+ shift_ratio[0] = (s16)((data->uFactorydata[2] << 8) +
+ data->uFactorydata[1]);
+ shift_ratio[1] = (s16)((data->uFactorydata[4] << 8) +
+ data->uFactorydata[3]);
+ shift_ratio[2] = (s16)((data->uFactorydata[6] << 8) +
+ data->uFactorydata[5]);
+ hw_result = (s8)data->uFactorydata[7];
+ total_count = (int)((data->uFactorydata[11] << 24) +
+ (data->uFactorydata[10] << 16) +
+ (data->uFactorydata[9] << 8) +
+ data->uFactorydata[8]);
+ avg[0] = (long)((data->uFactorydata[15] << 24) +
+ (data->uFactorydata[14] << 16) +
+ (data->uFactorydata[13] << 8) +
+ data->uFactorydata[12]);
+ avg[1] = (long)((data->uFactorydata[19] << 24) +
+ (data->uFactorydata[18] << 16) +
+ (data->uFactorydata[17] << 8) +
+ data->uFactorydata[16]);
+ avg[2] = (long)((data->uFactorydata[23] << 24) +
+ (data->uFactorydata[22] << 16) +
+ (data->uFactorydata[21] << 8) +
+ data->uFactorydata[20]);
+ rms[0] = (long)((data->uFactorydata[27] << 24) +
+ (data->uFactorydata[26] << 16) +
+ (data->uFactorydata[25] << 8) +
+ data->uFactorydata[24]);
+ rms[1] = (long)((data->uFactorydata[31] << 24) +
+ (data->uFactorydata[30] << 16) +
+ (data->uFactorydata[29] << 8) +
+ data->uFactorydata[28]);
+ rms[2] = (long)((data->uFactorydata[35] << 24) +
+ (data->uFactorydata[34] << 16) +
+ (data->uFactorydata[33] << 8) +
+ data->uFactorydata[32]);
+ pr_info("[SSP] init: %d, total cnt: %d\n", initialized, total_count);
+ pr_info("[SSP] hw_result: %d, %d, %d, %d\n", hw_result,
+ shift_ratio[0], shift_ratio[1], shift_ratio[2]);
+ pr_info("[SSP] avg %+8ld %+8ld %+8ld (LSB)\n", avg[0], avg[1], avg[2]);
+ pr_info("[SSP] rms %+8ld %+8ld %+8ld (LSB)\n", rms[0], rms[1], rms[2]);
+
+ if (hw_result < 0) {
+ pr_err("[SSP] %s - hw selftest fail(%d), sw selftest skip\n",
+ __func__, hw_result);
+ return sprintf(buf, "-1,0,0,0,0,0,0,%d.%d,%d.%d,%d.%d,0,0,0\n",
+ shift_ratio[0] / 10, shift_ratio[0] % 10,
+ shift_ratio[1] / 10, shift_ratio[1] % 10,
+ shift_ratio[2] / 10, shift_ratio[2] % 10);
+ }
+ gyro_bias[0] = (avg[0] * DEF_SCALE_FOR_FLOAT) / DEF_GYRO_SENS;
+ gyro_bias[1] = (avg[1] * DEF_SCALE_FOR_FLOAT) / DEF_GYRO_SENS;
+ gyro_bias[2] = (avg[2] * DEF_SCALE_FOR_FLOAT) / DEF_GYRO_SENS;
+ iCalData[0] = (s16)avg[0];
+ iCalData[1] = (s16)avg[1];
+ iCalData[2] = (s16)avg[2];
+
+ if (VERBOSE_OUT) {
+ pr_info("[SSP] abs bias: %+8d.%03d %+8d.%03d %+8d.%03d (dps)\n",
+ (int)abs(gyro_bias[0]) / DEF_SCALE_FOR_FLOAT,
+ (int)abs(gyro_bias[0]) % DEF_SCALE_FOR_FLOAT,
+ (int)abs(gyro_bias[1]) / DEF_SCALE_FOR_FLOAT,
+ (int)abs(gyro_bias[1]) % DEF_SCALE_FOR_FLOAT,
+ (int)abs(gyro_bias[2]) / DEF_SCALE_FOR_FLOAT,
+ (int)abs(gyro_bias[2]) % DEF_SCALE_FOR_FLOAT);
+ }
+
+ for (j = 0; j < 3; j++) {
+ if (unlikely(abs(avg[j]) > bias_thresh)) {
+ pr_err("[SSP] %s-Gyro bias (%ld) exceeded threshold "
+ "(threshold = %d LSB)\n", a_name[j],
+ avg[j], bias_thresh);
+ ret_val |= 1 << (3 + j);
+ }
+ }
+ /* 3rd, check RMS for dead gyros
+ If any of the RMS noise value returns zero,
+ then we might have dead gyro or FIFO/register failure,
+ the part is sleeping, or the part is not responsive */
+ if (rms[0] == 0 || rms[1] == 0 || rms[2] == 0)
+ ret_val |= 1 << 6;
+
+ if (VERBOSE_OUT) {
+ pr_info("[SSP] RMS ^ 2 : %+8ld %+8ld %+8ld\n",
+ (long)rms[0] / total_count,
+ (long)rms[1] / total_count, (long)rms[2] / total_count);
+ }
+
+ for (j = 0; j < 3; j++) {
+ if (unlikely(rms[j] / total_count > DEF_RMS_THRESH)) {
+ pr_err("[SSP] %s-Gyro rms (%ld) exceeded threshold "
+ "(threshold = %d LSB)\n", a_name[j],
+ rms[j] / total_count, DEF_RMS_THRESH);
+ ret_val |= 1 << (7 + j);
+ }
+ }
+
+ for (i = 0; i < 3; i++) {
+ if (rms[i] > 10000) {
+ temp =
+ ((u32) (rms[i] / total_count)) *
+ DEF_RMS_SCALE_FOR_RMS;
+ } else {
+ temp =
+ ((u32) (rms[i] * DEF_RMS_SCALE_FOR_RMS)) /
+ total_count;
+ }
+ if (rms[i] < 0)
+ temp = 1 << 31;
+
+ dps_rms[i] = mpu6050_selftest_sqrt(temp) / DEF_GYRO_SENS;
+
+ gyro_rms[i] =
+ dps_rms[i] * DEF_SCALE_FOR_FLOAT / DEF_SQRT_SCALE_FOR_RMS;
+ }
+
+ pr_info("[SSP] RMS : %+8d.%03d %+8d.%03d %+8d.%03d (dps)\n",
+ (int)abs(gyro_rms[0]) / DEF_SCALE_FOR_FLOAT,
+ (int)abs(gyro_rms[0]) % DEF_SCALE_FOR_FLOAT,
+ (int)abs(gyro_rms[1]) / DEF_SCALE_FOR_FLOAT,
+ (int)abs(gyro_rms[1]) % DEF_SCALE_FOR_FLOAT,
+ (int)abs(gyro_rms[2]) / DEF_SCALE_FOR_FLOAT,
+ (int)abs(gyro_rms[2]) % DEF_SCALE_FOR_FLOAT);
+
+ if (likely(!ret_val)) {
+ save_gyro_caldata(data, iCalData);
+ } else {
+ pr_err("[SSP] ret_val != 0, gyrocal is 0 at all axis\n");
+ data->gyrocal.x = 0;
+ data->gyrocal.y = 0;
+ data->gyrocal.z = 0;
+ }
+
+exit:
+ ssp_dbg("[SSP]: %s - %d,"
+ "%d.%03d,%d.%03d,%d.%03d,"
+ "%d.%03d,%d.%03d,%d.%03d,"
+ "%d.%d,%d.%d,%d.%d,"
+ "%d,%d,%d\n",
+ __func__, ret_val,
+ (int)abs(gyro_bias[0]/1000),
+ (int)abs(gyro_bias[0])%1000,
+ (int)abs(gyro_bias[1]/1000),
+ (int)abs(gyro_bias[1])%1000,
+ (int)abs(gyro_bias[2]/1000),
+ (int)abs(gyro_bias[2])%1000,
+ gyro_rms[0]/1000,
+ (int)abs(gyro_rms[0])%1000,
+ gyro_rms[1]/1000,
+ (int)abs(gyro_rms[1])%1000,
+ gyro_rms[2]/1000,
+ (int)abs(gyro_rms[2])%1000,
+ shift_ratio[0] / 10, shift_ratio[0] % 10,
+ shift_ratio[1] / 10, shift_ratio[1] % 10,
+ shift_ratio[2] / 10, shift_ratio[2] % 10,
+ (int)(total_count/3),
+ (int)(total_count/3),
+ (int)(total_count/3));
+
+ return sprintf(buf, "%d,"
+ "%d.%03d,%d.%03d,%d.%03d,"
+ "%d.%03d,%d.%03d,%d.%03d,"
+ "%d.%d,%d.%d,%d.%d,"
+ "%d,%d,%d\n",
+ ret_val,
+ (int)abs(gyro_bias[0]/1000),
+ (int)abs(gyro_bias[0])%1000,
+ (int)abs(gyro_bias[1]/1000),
+ (int)abs(gyro_bias[1])%1000,
+ (int)abs(gyro_bias[2]/1000),
+ (int)abs(gyro_bias[2])%1000,
+ gyro_rms[0]/1000,
+ (int)abs(gyro_rms[0])%1000,
+ gyro_rms[1]/1000,
+ (int)abs(gyro_rms[1])%1000,
+ gyro_rms[2]/1000,
+ (int)abs(gyro_rms[2])%1000,
+ shift_ratio[0] / 10, shift_ratio[0] % 10,
+ shift_ratio[1] / 10, shift_ratio[1] % 10,
+ shift_ratio[2] / 10, shift_ratio[2] % 10,
+ (int)(total_count/3),
+ (int)(total_count/3),
+ (int)(total_count/3));
+}
+
+static ssize_t gyro_selftest_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ return mpu6500_gyro_selftest(buf, data);
+}
+
+static ssize_t gyro_selftest_dps_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int iNewDps = 0;
+ int iDelayCnt = 0, iRet = 0;
+ char chTempBuf[2] = { 0, 10 };
+
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ if (!(data->uSensorState & (1 << GYROSCOPE_SENSOR)))
+ goto exit;
+
+ sscanf(buf, "%d", &iNewDps);
+
+ if (iNewDps == GYROSCOPE_DPS250)
+ chTempBuf[0] = 0;
+ else if (iNewDps == GYROSCOPE_DPS500)
+ chTempBuf[0] = 1;
+ else if (iNewDps == GYROSCOPE_DPS2000)
+ chTempBuf[0] = 2;
+ else {
+ chTempBuf[0] = 1;
+ iNewDps = GYROSCOPE_DPS500;
+ }
+
+ data->uFactorydataReady = 0;
+ memset(data->uFactorydata, 0, sizeof(char) * FACTORY_DATA_MAX);
+
+ iRet = send_instruction(data, FACTORY_MODE, GYROSCOPE_DPS_FACTORY,
+ chTempBuf, 2);
+
+ while (!(data->uFactorydataReady & (1 << GYROSCOPE_DPS_FACTORY))
+ && (iDelayCnt++ < 150)
+ && (iRet == SUCCESS))
+ msleep(20);
+
+ if ((iDelayCnt >= 150) || (iRet != SUCCESS)) {
+ pr_err("[SSP]: %s - Gyro Selftest DPS Timeout!!\n", __func__);
+ goto exit;
+ }
+
+ mdelay(5);
+
+ if (data->uFactorydata[0] != SUCCESS) {
+ pr_err("[SSP]: %s - Gyro Selftest DPS Error!!\n", __func__);
+ goto exit;
+ }
+
+ data->uGyroDps = (unsigned int)iNewDps;
+ pr_err("[SSP]: %s - %u dps stored\n", __func__, data->uGyroDps);
+exit:
+ return count;
+}
+
+static ssize_t gyro_selftest_dps_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", data->uGyroDps);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, gyro_name_show, NULL);
+static DEVICE_ATTR(vendor, S_IRUGO, gyro_vendor_show, NULL);
+static DEVICE_ATTR(power_off, S_IRUGO, gyro_power_off, NULL);
+static DEVICE_ATTR(power_on, S_IRUGO, gyro_power_on, NULL);
+static DEVICE_ATTR(temperature, S_IRUGO, gyro_get_temp, NULL);
+static DEVICE_ATTR(selftest, S_IRUGO, gyro_selftest_show, NULL);
+static DEVICE_ATTR(selftest_dps, S_IRUGO | S_IWUSR | S_IWGRP,
+ gyro_selftest_dps_show, gyro_selftest_dps_store);
+
+static struct device_attribute *gyro_attrs[] = {
+ &dev_attr_name,
+ &dev_attr_vendor,
+ &dev_attr_selftest,
+ &dev_attr_power_on,
+ &dev_attr_power_off,
+ &dev_attr_temperature,
+ &dev_attr_selftest_dps,
+ NULL,
+};
+
+void initialize_gyro_factorytest(struct ssp_data *data)
+{
+ sensors_register(data->gyro_device, data, gyro_attrs, "gyro_sensor");
+}
+
+void remove_gyro_factorytest(struct ssp_data *data)
+{
+ sensors_unregister(data->gyro_device, gyro_attrs);
+}
diff --git a/drivers/sensorhub/stm/factory/light_cm3320.c b/drivers/sensorhub/stm/factory/light_cm3320.c
new file mode 100755
index 0000000..a6438d0
--- /dev/null
+++ b/drivers/sensorhub/stm/factory/light_cm3320.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012, Samsung Electronics Co. Ltd. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "../ssp.h"
+
+#define VENDOR "CAPELLA"
+#define CHIP_ID_3320 "CM3320"
+#define CHIP_ID "CM3323"
+
+/*************************************************************************/
+/* factory Sysfs */
+/*************************************************************************/
+static ssize_t light_vendor_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", VENDOR);
+}
+
+static ssize_t light_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", CHIP_ID_3320);
+}
+
+static ssize_t light_lux_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u,%u,%u,%u\n",
+ data->buf[LIGHT_SENSOR].r, data->buf[LIGHT_SENSOR].g,
+ data->buf[LIGHT_SENSOR].b, data->buf[LIGHT_SENSOR].w);
+}
+
+static ssize_t light_data_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u,%u,%u,%u\n",
+ data->buf[LIGHT_SENSOR].r, data->buf[LIGHT_SENSOR].g,
+ data->buf[LIGHT_SENSOR].b, data->buf[LIGHT_SENSOR].w);
+}
+
+static DEVICE_ATTR(vendor, S_IRUGO, light_vendor_show, NULL);
+static DEVICE_ATTR(name, S_IRUGO, light_name_show, NULL);
+static DEVICE_ATTR(lux, S_IRUGO, light_lux_show, NULL);
+static DEVICE_ATTR(raw_data, S_IRUGO, light_data_show, NULL);
+
+static struct device_attribute *light_attrs[] = {
+ &dev_attr_vendor,
+ &dev_attr_name,
+ &dev_attr_lux,
+ &dev_attr_raw_data,
+ NULL,
+};
+
+void initialize_light_factorytest(struct ssp_data *data)
+{
+ sensors_register(data->light_device, data, light_attrs, "light_sensor");
+}
+
+void remove_light_factorytest(struct ssp_data *data)
+{
+ sensors_unregister(data->light_device, light_attrs);
+}
diff --git a/drivers/sensorhub/stm/factory/magnetic_yas532.c b/drivers/sensorhub/stm/factory/magnetic_yas532.c
new file mode 100755
index 0000000..be9a38f
--- /dev/null
+++ b/drivers/sensorhub/stm/factory/magnetic_yas532.c
@@ -0,0 +1,456 @@
+/*
+ * Copyright (C) 2012, Samsung Electronics Co. Ltd. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "../ssp.h"
+
+/*************************************************************************/
+/* factory Sysfs */
+/*************************************************************************/
+
+#define VENDOR "YAMAHA"
+#define CHIP_ID "YAS532"
+#define MAG_HW_OFFSET_FILE_PATH "/efs/hw_offset"
+
+int mag_open_hwoffset(struct ssp_data *data)
+{
+ int iRet = 0;
+ mm_segment_t old_fs;
+ struct file *cal_filp = NULL;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ cal_filp = filp_open(MAG_HW_OFFSET_FILE_PATH, O_RDONLY, 0666);
+ if (IS_ERR(cal_filp)) {
+ pr_err("[SSP] %s: filp_open failed\n", __func__);
+ set_fs(old_fs);
+ iRet = PTR_ERR(cal_filp);
+
+ data->magoffset.x = 0;
+ data->magoffset.y = 0;
+ data->magoffset.z = 0;
+
+ return iRet;
+ }
+
+ iRet = cal_filp->f_op->read(cal_filp, (char *)&data->magoffset,
+ 3 * sizeof(char), &cal_filp->f_pos);
+ if (iRet != 3 * sizeof(char)) {
+ pr_err("[SSP] %s: filp_open failed\n", __func__);
+ iRet = -EIO;
+ }
+
+ filp_close(cal_filp, current->files);
+ set_fs(old_fs);
+
+ ssp_dbg("[SSP]: %s: %d, %d, %d\n", __func__,
+ (s8)data->magoffset.x,
+ (s8)data->magoffset.y,
+ (s8)data->magoffset.z);
+
+ if ((data->magoffset.x == 0) && (data->magoffset.y == 0)
+ && (data->magoffset.z == 0))
+ return ERROR;
+
+ return iRet;
+}
+
+int mag_store_hwoffset(struct ssp_data *data)
+{
+ int iRet = 0;
+ struct file *cal_filp = NULL;
+ mm_segment_t old_fs;
+
+ if (get_hw_offset(data) < 0) {
+ pr_err("[SSP]: %s - get_hw_offset failed\n", __func__);
+ return ERROR;
+ } else {
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ cal_filp = filp_open(MAG_HW_OFFSET_FILE_PATH,
+ O_CREAT | O_TRUNC | O_WRONLY, 0666);
+ if (IS_ERR(cal_filp)) {
+ pr_err("[SSP]: %s - Can't open hw_offset file\n",
+ __func__);
+ set_fs(old_fs);
+ iRet = PTR_ERR(cal_filp);
+ return iRet;
+ }
+ iRet = cal_filp->f_op->write(cal_filp,
+ (char *)&data->magoffset,
+ 3 * sizeof(char), &cal_filp->f_pos);
+ if (iRet != 3 * sizeof(char)) {
+ pr_err("[SSP]: %s - Can't write the hw_offset"
+ " to file\n", __func__);
+ iRet = -EIO;
+ }
+ filp_close(cal_filp, current->files);
+ set_fs(old_fs);
+ return iRet;
+ }
+}
+
+int set_hw_offset(struct ssp_data *data)
+{
+ char chTxBuf[4] = { 0, };
+ char chRxBuf = 0;
+ int iRet = 0;
+
+ if (waiting_wakeup_mcu(data) < 0 ||
+ data->fw_dl_state == FW_DL_STATE_DOWNLOADING) {
+ pr_info("[SSP] : %s, skip DL state = %d\n", __func__,
+ data->fw_dl_state);
+ return FAIL;
+ }
+
+ chTxBuf[0] = MSG2SSP_AP_SET_MAGNETIC_HWOFFSET;
+ chTxBuf[1] = data->magoffset.x;
+ chTxBuf[2] = data->magoffset.y;
+ chTxBuf[3] = data->magoffset.z;
+
+ iRet = ssp_read_data(data, chTxBuf, 4, &chRxBuf, 1, DEFAULT_RETRIES);
+ if ((chRxBuf != MSG_ACK) || (iRet != SUCCESS)) {
+ pr_err("[SSP]: %s - spi fail %d, %d\n",
+ __func__, iRet, chRxBuf);
+ iRet = ERROR;
+ }
+
+ pr_info("[SSP]: %s: x: %d, y: %d, z: %d\n", __func__,
+ (s8)chTxBuf[1], (s8)chTxBuf[2], (s8)chTxBuf[3]);
+ return iRet;
+}
+
+int get_hw_offset(struct ssp_data *data)
+{
+ char chTxBuf = 0;
+ char chRxBuf[3] = { 0, };
+ int iRet = 0;
+
+ if (waiting_wakeup_mcu(data) < 0)
+ return ERROR;
+
+ chTxBuf = MSG2SSP_AP_GET_MAGNETIC_HWOFFSET;
+
+ data->magoffset.x = 0;
+ data->magoffset.y = 0;
+ data->magoffset.z = 0;
+
+ iRet = ssp_read_data(data, &chTxBuf, 1, chRxBuf, 3, DEFAULT_RETRIES);
+ if (iRet != SUCCESS) {
+ pr_err("[SSP]: %s - spi fail %d\n", __func__, iRet);
+ iRet = ERROR;
+ }
+
+ data->magoffset.x = chRxBuf[0];
+ data->magoffset.y = chRxBuf[1];
+ data->magoffset.z = chRxBuf[2];
+
+ pr_info("[SSP]: %s: x: %d, y: %d, z: %d\n", __func__,
+ (s8)data->magoffset.x,
+ (s8)data->magoffset.y,
+ (s8)data->magoffset.z);
+ return iRet;
+}
+
+static ssize_t magnetic_vendor_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", VENDOR);
+}
+
+static ssize_t magnetic_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", CHIP_ID);
+}
+
+static int check_rawdata_spec(struct ssp_data *data)
+{
+ if ((data->buf[GEOMAGNETIC_SENSOR].x == 0) &&
+ (data->buf[GEOMAGNETIC_SENSOR].y == 0) &&
+ (data->buf[GEOMAGNETIC_SENSOR].z == 0))
+ return FAIL;
+ else
+ return SUCCESS;
+}
+
+static ssize_t raw_data_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ pr_info("[SSP] %s - %d,%d,%d\n", __func__,
+ data->buf[GEOMAGNETIC_SENSOR].x,
+ data->buf[GEOMAGNETIC_SENSOR].y,
+ data->buf[GEOMAGNETIC_SENSOR].z);
+
+ if (data->bGeomagneticRawEnabled == false) {
+ data->buf[GEOMAGNETIC_SENSOR].x = -1;
+ data->buf[GEOMAGNETIC_SENSOR].y = -1;
+ data->buf[GEOMAGNETIC_SENSOR].z = -1;
+ } else {
+ if (data->buf[GEOMAGNETIC_SENSOR].x > 18000)
+ data->buf[GEOMAGNETIC_SENSOR].x = 18000;
+ else if (data->buf[GEOMAGNETIC_SENSOR].x < -18000)
+ data->buf[GEOMAGNETIC_SENSOR].x = -18000;
+ if (data->buf[GEOMAGNETIC_SENSOR].y > 18000)
+ data->buf[GEOMAGNETIC_SENSOR].y = 18000;
+ else if (data->buf[GEOMAGNETIC_SENSOR].y < -18000)
+ data->buf[GEOMAGNETIC_SENSOR].y = -18000;
+ if (data->buf[GEOMAGNETIC_SENSOR].z > 18000)
+ data->buf[GEOMAGNETIC_SENSOR].z = 18000;
+ else if (data->buf[GEOMAGNETIC_SENSOR].z < -18000)
+ data->buf[GEOMAGNETIC_SENSOR].z = -18000;
+ }
+ return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n",
+ data->buf[GEOMAGNETIC_SENSOR].x,
+ data->buf[GEOMAGNETIC_SENSOR].y,
+ data->buf[GEOMAGNETIC_SENSOR].z);
+}
+
+static ssize_t raw_data_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ char chTempbuf[2] = { 1, 20};
+ int iRet;
+ int64_t dEnable;
+ int iRetries = 50;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ iRet = kstrtoll(buf, 10, &dEnable);
+ if (iRet < 0)
+ return iRet;
+
+ if (dEnable) {
+ data->buf[GEOMAGNETIC_SENSOR].x = 0;
+ data->buf[GEOMAGNETIC_SENSOR].y = 0;
+ data->buf[GEOMAGNETIC_SENSOR].z = 0;
+
+ send_instruction(data, ADD_SENSOR, GEOMAGNETIC_RAW,
+ chTempbuf, 2);
+
+ do {
+ msleep(20);
+ if (check_rawdata_spec(data) == SUCCESS)
+ break;
+ } while (--iRetries);
+
+ if (iRetries > 0) {
+ pr_info("[SSP] %s - success, %d\n", __func__, iRetries);
+ data->bGeomagneticRawEnabled = true;
+ } else {
+ pr_err("[SSP] %s - wait timeout, %d\n", __func__,
+ iRetries);
+ data->bGeomagneticRawEnabled = false;
+ }
+ } else {
+ send_instruction(data, REMOVE_SENSOR, GEOMAGNETIC_RAW,
+ chTempbuf, 2);
+ data->bGeomagneticRawEnabled = false;
+ }
+
+ return size;
+}
+
+static int check_data_spec(struct ssp_data *data)
+{
+ if ((data->buf[GEOMAGNETIC_SENSOR].x == 0) &&
+ (data->buf[GEOMAGNETIC_SENSOR].y == 0) &&
+ (data->buf[GEOMAGNETIC_SENSOR].z == 0))
+ return FAIL;
+ else if ((data->buf[GEOMAGNETIC_SENSOR].x > 6500) ||
+ (data->buf[GEOMAGNETIC_SENSOR].x < -6500) ||
+ (data->buf[GEOMAGNETIC_SENSOR].y > 6500) ||
+ (data->buf[GEOMAGNETIC_SENSOR].y < -6500) ||
+ (data->buf[GEOMAGNETIC_SENSOR].z > 6500) ||
+ (data->buf[GEOMAGNETIC_SENSOR].z < -6500))
+ return FAIL;
+ else
+ return SUCCESS;
+}
+
+static ssize_t adc_data_read(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ bool bSuccess = false;
+ u8 chTempbuf[2] = {1, 20};
+ s16 iSensorBuf[3] = {0, };
+ int iRetries = 10;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ data->buf[GEOMAGNETIC_SENSOR].x = 0;
+ data->buf[GEOMAGNETIC_SENSOR].y = 0;
+ data->buf[GEOMAGNETIC_SENSOR].z = 0;
+
+ if (!(atomic_read(&data->aSensorEnable) & (1 << GEOMAGNETIC_SENSOR)))
+ send_instruction(data, ADD_SENSOR, GEOMAGNETIC_SENSOR,
+ chTempbuf, 2);
+
+ do {
+ msleep(60);
+ if (check_data_spec(data) == SUCCESS)
+ break;
+ } while (--iRetries);
+
+ if (iRetries > 0)
+ bSuccess = true;
+
+ iSensorBuf[0] = data->buf[GEOMAGNETIC_SENSOR].x;
+ iSensorBuf[1] = data->buf[GEOMAGNETIC_SENSOR].y;
+ iSensorBuf[2] = data->buf[GEOMAGNETIC_SENSOR].z;
+
+ if (!(atomic_read(&data->aSensorEnable) & (1 << GEOMAGNETIC_SENSOR)))
+ send_instruction(data, REMOVE_SENSOR, GEOMAGNETIC_SENSOR,
+ chTempbuf, 2);
+
+ pr_info("[SSP]: %s - x = %d, y = %d, z = %d\n", __func__,
+ iSensorBuf[0], iSensorBuf[1], iSensorBuf[2]);
+
+ return sprintf(buf, "%s,%d,%d,%d\n", (bSuccess ? "OK" : "NG"),
+ iSensorBuf[0], iSensorBuf[1], iSensorBuf[2]);
+}
+
+static ssize_t magnetic_get_selftest(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ char chTempBuf[2] = { 0, 10 };
+ int iDelayCnt = 0, iRet = 0, iTimeoutReties = 0;
+ s8 id = 0, x = 0, y1 = 0, y2 = 0, dir = 0;
+ s16 sx = 0, sy = 0, ohx = 0, ohy = 0, ohz = 0;
+ s8 err[7] = {0, };
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+reties:
+ iDelayCnt = 0;
+ data->uFactorydataReady = 0;
+ memset(data->uFactorydata, 0, sizeof(char) * FACTORY_DATA_MAX);
+
+ iRet = send_instruction(data, FACTORY_MODE, GEOMAGNETIC_FACTORY,
+ chTempBuf, 2);
+
+ while (!(data->uFactorydataReady & (1 << GEOMAGNETIC_FACTORY))
+ && (iDelayCnt++ < 50)
+ && (iRet == SUCCESS))
+ msleep(20);
+
+ if ((iDelayCnt >= 50) || (iRet != SUCCESS)) {
+ pr_err("[SSP]: %s - Magnetic Selftest Timeout!! %d\n",
+ __func__, iRet);
+ if (iTimeoutReties++ < 3)
+ goto reties;
+ else
+ goto exit;
+ }
+
+ mdelay(5);
+
+ id = (s8)(data->uFactorydata[0]);
+ err[0] = (s8)(data->uFactorydata[1]);
+ err[1] = (s8)(data->uFactorydata[2]);
+ err[2] = (s8)(data->uFactorydata[3]);
+ x = (s8)(data->uFactorydata[4]);
+ y1 = (s8)(data->uFactorydata[5]);
+ y2 = (s8)(data->uFactorydata[6]);
+ err[3] = (s8)(data->uFactorydata[7]);
+ dir = (s8)(data->uFactorydata[8]);
+ err[4] = (s8)(data->uFactorydata[9]);
+ ohx = (s16)((data->uFactorydata[10] << 8) + data->uFactorydata[11]);
+ ohy = (s16)((data->uFactorydata[12] << 8) + data->uFactorydata[13]);
+ ohz = (s16)((data->uFactorydata[14] << 8) + data->uFactorydata[15]);
+ err[6] = (s8)(data->uFactorydata[16]);
+ sx = (s16)((data->uFactorydata[17] << 8) + data->uFactorydata[18]);
+ sy = (s16)((data->uFactorydata[19] << 8) + data->uFactorydata[20]);
+ err[5] = (s8)(data->uFactorydata[21]);
+
+ if (unlikely(id != 0x2))
+ err[0] = -1;
+ if (unlikely(x < -30 || x > 30))
+ err[3] = -1;
+ if (unlikely(y1 < -30 || y1 > 30))
+ err[3] = -1;
+ if (unlikely(y2 < -30 || y2 > 30))
+ err[3] = -1;
+ if (unlikely(sx < 17 || sy < 22))
+ err[5] = -1;
+ if (unlikely(ohx < -600 || ohx > 600))
+ err[6] = -1;
+ if (unlikely(ohy < -600 || ohy > 600))
+ err[6] = -1;
+ if (unlikely(ohz < -600 || ohz > 600))
+ err[6] = -1;
+
+ pr_info("[SSP] %s\n"
+ "[SSP] Test1 - err = %d, id = %d\n"
+ "[SSP] Test3 - err = %d\n"
+ "[SSP] Test4 - err = %d, offset = %d,%d,%d\n"
+ "[SSP] Test5 - err = %d, direction = %d\n"
+ "[SSP] Test6 - err = %d, sensitivity = %d,%d\n"
+ "[SSP] Test7 - err = %d, offset = %d,%d,%d\n"
+ "[SSP] Test2 - err = %d\n",
+ __func__, err[0], id, err[2], err[3], x, y1, y2, err[4], dir,
+ err[5], sx, sy, err[6], ohx, ohy, ohz, err[1]);
+
+exit:
+ return sprintf(buf,
+ "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
+ err[0], id, err[2], err[3], x, y1, y2, err[4], dir,
+ err[5], sx, sy, err[6], ohx, ohy, ohz, err[1]);
+}
+
+static ssize_t hw_offset_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ mag_open_hwoffset(data);
+
+ pr_info("[SSP] %s: %d %d %d\n", __func__,
+ (s8)data->magoffset.x,
+ (s8)data->magoffset.y,
+ (s8)data->magoffset.z);
+
+ return sprintf(buf, "%d %d %d\n",
+ (s8)data->magoffset.x,
+ (s8)data->magoffset.y,
+ (s8)data->magoffset.z);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, magnetic_name_show, NULL);
+static DEVICE_ATTR(vendor, S_IRUGO, magnetic_vendor_show, NULL);
+static DEVICE_ATTR(raw_data, S_IRUGO | S_IWUSR | S_IWGRP,
+ raw_data_show, raw_data_store);
+static DEVICE_ATTR(adc, S_IRUGO, adc_data_read, NULL);
+static DEVICE_ATTR(selftest, S_IRUGO, magnetic_get_selftest, NULL);
+static DEVICE_ATTR(hw_offset, S_IRUGO, hw_offset_show, NULL);
+
+static struct device_attribute *mag_attrs[] = {
+ &dev_attr_name,
+ &dev_attr_vendor,
+ &dev_attr_adc,
+ &dev_attr_raw_data,
+ &dev_attr_selftest,
+ &dev_attr_hw_offset,
+ NULL,
+};
+
+void initialize_magnetic_factorytest(struct ssp_data *data)
+{
+ sensors_register(data->mag_device, data, mag_attrs, "magnetic_sensor");
+}
+
+void remove_magnetic_factorytest(struct ssp_data *data)
+{
+ sensors_unregister(data->mag_device, mag_attrs);
+}
diff --git a/drivers/sensorhub/stm/factory/mcu_atuc128l5har.c b/drivers/sensorhub/stm/factory/mcu_atuc128l5har.c
new file mode 100755
index 0000000..7f6a7a1
--- /dev/null
+++ b/drivers/sensorhub/stm/factory/mcu_atuc128l5har.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2012, Samsung Electronics Co. Ltd. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "../ssp.h"
+
+/*************************************************************************/
+/* factory Sysfs */
+/*************************************************************************/
+
+#define MODEL_NAME "ATUC128L5HAR"
+
+ssize_t mcu_revision_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "AT01%u,AT01%u\n", data->uCurFirmRev,
+ get_module_rev(data));
+}
+
+ssize_t mcu_model_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", MODEL_NAME);
+}
+
+ssize_t mcu_update_kernel_bin_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ bool bSuccess = false;
+ int iRet = 0;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ ssp_dbg("[SSP]: %s - mcu binany update!\n", __func__);
+
+ iRet = forced_to_download_binary(data, UMS_BINARY);
+ if (iRet == SUCCESS) {
+ bSuccess = true;
+ goto out;
+ }
+
+ iRet = forced_to_download_binary(data, KERNEL_BINARY);
+ if (iRet == SUCCESS)
+ bSuccess = true;
+ else
+ bSuccess = false;
+out:
+ return sprintf(buf, "%s\n", (bSuccess ? "OK" : "NG"));
+}
+
+ssize_t mcu_update_kernel_crashed_bin_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ bool bSuccess = false;
+ int iRet = 0;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ ssp_dbg("[SSP]: %s - mcu binany update!\n", __func__);
+
+ iRet = forced_to_download_binary(data, UMS_BINARY);
+ if (iRet == SUCCESS) {
+ bSuccess = true;
+ goto out;
+ }
+
+ iRet = forced_to_download_binary(data, KERNEL_CRASHED_BINARY);
+ if (iRet == SUCCESS)
+ bSuccess = true;
+ else
+ bSuccess = false;
+out:
+ return sprintf(buf, "%s\n", (bSuccess ? "OK" : "NG"));
+}
+
+ssize_t mcu_update_ums_bin_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ bool bSuccess = false;
+ int iRet = 0;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ ssp_dbg("[SSP]: %s - mcu binany update!\n", __func__);
+
+ iRet = forced_to_download_binary(data, UMS_BINARY);
+ if (iRet == SUCCESS)
+ bSuccess = true;
+ else
+ bSuccess = false;
+
+ return sprintf(buf, "%s\n", (bSuccess ? "OK" : "NG"));
+}
+
+ssize_t mcu_reset_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ reset_mcu(data);
+
+ return sprintf(buf, "OK\n");
+}
+
+ssize_t mcu_factorytest_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+ char chTempBuf[2] = {0, 10};
+ int iRet = 0;
+
+ if (sysfs_streq(buf, "1")) {
+ data->uFactorydataReady = 0;
+ memset(data->uFactorydata, 0, sizeof(char) * FACTORY_DATA_MAX);
+
+ data->bMcuIRQTestSuccessed = false;
+ data->uTimeOutCnt = 0;
+
+ iRet = send_instruction(data, FACTORY_MODE,
+ MCU_FACTORY, chTempBuf, 2);
+ if (data->uTimeOutCnt == 0)
+ data->bMcuIRQTestSuccessed = true;
+ } else {
+ pr_err("[SSP]: %s - invalid value %d\n", __func__, *buf);
+ return -EINVAL;
+ }
+
+ ssp_dbg("[SSP]: MCU Factory Test Start! - %d\n", iRet);
+
+ return size;
+}
+
+ssize_t mcu_factorytest_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ bool bMcuTestSuccessed = false;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ if (data->bSspShutdown == true) {
+ ssp_dbg("[SSP]: %s - MCU Bin is crashed\n", __func__);
+ return sprintf(buf, "NG,NG,NG\n");
+ }
+
+ if (data->uFactorydataReady & (1 << MCU_FACTORY)) {
+ ssp_dbg("[SSP] MCU Factory Test Data : %u, %u, %u, %u, %u\n",
+ data->uFactorydata[0], data->uFactorydata[1],
+ data->uFactorydata[2], data->uFactorydata[3],
+ data->uFactorydata[4]);
+
+ /* system clock, RTC, I2C Master, I2C Slave, externel pin */
+ if ((data->uFactorydata[0] == SUCCESS)
+ && (data->uFactorydata[1] == SUCCESS)
+ && (data->uFactorydata[2] == SUCCESS)
+ && (data->uFactorydata[3] == SUCCESS)
+ && (data->uFactorydata[4] == SUCCESS))
+ bMcuTestSuccessed = true;
+ } else {
+ pr_err("[SSP]: %s - The Sensorhub is not ready %u\n", __func__,
+ data->uFactorydataReady);
+ }
+
+ ssp_dbg("[SSP]: MCU Factory Test Result - %s, %s, %s\n", MODEL_NAME,
+ (data->bMcuIRQTestSuccessed ? "OK" : "NG"),
+ (bMcuTestSuccessed ? "OK" : "NG"));
+
+ return sprintf(buf, "%s,%s,%s\n", MODEL_NAME,
+ (data->bMcuIRQTestSuccessed ? "OK" : "NG"),
+ (bMcuTestSuccessed ? "OK" : "NG"));
+}
+
+ssize_t mcu_sleep_factorytest_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+ char chTempBuf[2] = {0, 10};
+ int iRet = 0;
+
+ if (sysfs_streq(buf, "1")) {
+ data->uFactorydataReady = 0;
+ memset(data->uFactorydata, 0, sizeof(char) * FACTORY_DATA_MAX);
+
+ iRet = send_instruction(data, FACTORY_MODE,
+ MCU_SLEEP_FACTORY, chTempBuf, 2);
+ } else {
+ pr_err("[SSP]: %s - invalid value %d\n", __func__, *buf);
+ return -EINVAL;
+ }
+
+ ssp_dbg("[SSP]: MCU Sleep Factory Test Start! - %d\n", iRet);
+
+ return size;
+}
+
+ssize_t mcu_sleep_factorytest_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int iDataIdx, iSensorData = 0;
+ struct ssp_data *data = dev_get_drvdata(dev);
+ struct sensor_value fsb[SENSOR_MAX];
+
+ if (!(data->uFactorydataReady & (1 << MCU_SLEEP_FACTORY))) {
+ pr_err("[SSP]: %s - The Sensorhub is not ready\n", __func__);
+ goto exit;
+ }
+
+ for (iDataIdx = 0; iDataIdx < FACTORY_DATA_MAX;) {
+ iSensorData = (int)data->uFactorydata[iDataIdx++];
+
+ if ((iSensorData < 0) ||
+ (iSensorData >= (SENSOR_MAX - 1))) {
+ pr_err("[SSP]: %s - Mcu data frame error %d\n",
+ __func__, iSensorData);
+ goto exit;
+ }
+
+ data->get_sensor_data[iSensorData]((char *)data->uFactorydata,
+ &iDataIdx, &(fsb[iSensorData]));
+ }
+
+ convert_acc_data(&fsb[ACCELEROMETER_SENSOR].x);
+ convert_acc_data(&fsb[ACCELEROMETER_SENSOR].y);
+ convert_acc_data(&fsb[ACCELEROMETER_SENSOR].z);
+
+ fsb[ACCELEROMETER_SENSOR].x -= data->accelcal.x;
+ fsb[ACCELEROMETER_SENSOR].y -= data->accelcal.y;
+ fsb[ACCELEROMETER_SENSOR].z -= data->accelcal.z;
+
+ fsb[GYROSCOPE_SENSOR].x -= data->gyrocal.x;
+ fsb[GYROSCOPE_SENSOR].y -= data->gyrocal.y;
+ fsb[GYROSCOPE_SENSOR].z -= data->gyrocal.z;
+
+ fsb[PRESSURE_SENSOR].pressure[0] -= data->iPressureCal;
+
+exit:
+ ssp_dbg("[SSP]: %s Result\n"
+ "accel %d,%d,%d\n"
+ "gyro %d,%d,%d\n"
+ "mag %d,%d,%d\n"
+ "baro %d,%d\n"
+ "ges %d,%d,%d,%d\n"
+ "prox %u,%u\n"
+ "temp %d,%d,%d\n"
+ "light %u,%u,%u,%u\n", __func__,
+ fsb[ACCELEROMETER_SENSOR].x, fsb[ACCELEROMETER_SENSOR].y,
+ fsb[ACCELEROMETER_SENSOR].z, fsb[GYROSCOPE_SENSOR].x,
+ fsb[GYROSCOPE_SENSOR].y, fsb[GYROSCOPE_SENSOR].z,
+ fsb[GEOMAGNETIC_SENSOR].x, fsb[GEOMAGNETIC_SENSOR].y,
+ fsb[GEOMAGNETIC_SENSOR].z, fsb[PRESSURE_SENSOR].pressure[0],
+ fsb[PRESSURE_SENSOR].pressure[1],
+ fsb[GESTURE_SENSOR].data[0], fsb[GESTURE_SENSOR].data[1],
+ fsb[GESTURE_SENSOR].data[2], fsb[GESTURE_SENSOR].data[3],
+ fsb[PROXIMITY_SENSOR].prox[0], fsb[PROXIMITY_SENSOR].prox[1],
+ fsb[TEMPERATURE_HUMIDITY_SENSOR].data[0],
+ fsb[TEMPERATURE_HUMIDITY_SENSOR].data[1],
+ fsb[TEMPERATURE_HUMIDITY_SENSOR].data[2],
+ fsb[LIGHT_SENSOR].r, fsb[LIGHT_SENSOR].g, fsb[LIGHT_SENSOR].b,
+ fsb[LIGHT_SENSOR].w);
+
+ return sprintf(buf, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%u,"
+ "%u,%u,%u,%u,%d,%d,%d,%d,%d,%d\n",
+ fsb[ACCELEROMETER_SENSOR].x, fsb[ACCELEROMETER_SENSOR].y,
+ fsb[ACCELEROMETER_SENSOR].z, fsb[GYROSCOPE_SENSOR].x,
+ fsb[GYROSCOPE_SENSOR].y, fsb[GYROSCOPE_SENSOR].z,
+ fsb[GEOMAGNETIC_SENSOR].x, fsb[GEOMAGNETIC_SENSOR].y,
+ fsb[GEOMAGNETIC_SENSOR].z, fsb[PRESSURE_SENSOR].pressure[0],
+ fsb[PRESSURE_SENSOR].pressure[1], fsb[PROXIMITY_SENSOR].prox[1],
+ fsb[LIGHT_SENSOR].r, fsb[LIGHT_SENSOR].g, fsb[LIGHT_SENSOR].b,
+ fsb[LIGHT_SENSOR].w,
+ fsb[GESTURE_SENSOR].data[0], fsb[GESTURE_SENSOR].data[1],
+ fsb[GESTURE_SENSOR].data[2], fsb[GESTURE_SENSOR].data[3],
+ fsb[TEMPERATURE_HUMIDITY_SENSOR].data[0],
+ fsb[TEMPERATURE_HUMIDITY_SENSOR].data[1]);
+}
diff --git a/drivers/sensorhub/stm/factory/mcu_stm32f401.c b/drivers/sensorhub/stm/factory/mcu_stm32f401.c
new file mode 100755
index 0000000..b49fffc
--- /dev/null
+++ b/drivers/sensorhub/stm/factory/mcu_stm32f401.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2012, Samsung Electronics Co. Ltd. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "../ssp.h"
+
+/*************************************************************************/
+/* factory Sysfs */
+/*************************************************************************/
+
+#define MODEL_NAME "STM32F401CCY6B"
+
+ssize_t mcu_revision_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "ST01%u,ST01%u\n", data->uCurFirmRev,
+ get_module_rev(data));
+}
+
+ssize_t mcu_model_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", MODEL_NAME);
+}
+
+ssize_t mcu_update_kernel_bin_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ bool bSuccess = false;
+ int iRet = 0;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ ssp_dbg("[SSP]: %s - mcu binany update!\n", __func__);
+
+ iRet = forced_to_download_binary(data, UMS_BINARY);
+ if (iRet == SUCCESS) {
+ bSuccess = true;
+ goto out;
+ }
+
+ iRet = forced_to_download_binary(data, KERNEL_BINARY);
+ if (iRet == SUCCESS)
+ bSuccess = true;
+ else
+ bSuccess = false;
+out:
+ return sprintf(buf, "%s\n", (bSuccess ? "OK" : "NG"));
+}
+
+ssize_t mcu_update_kernel_crashed_bin_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ bool bSuccess = false;
+ int iRet = 0;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ ssp_dbg("[SSP]: %s - mcu binany update!\n", __func__);
+
+ iRet = forced_to_download_binary(data, UMS_BINARY);
+ if (iRet == SUCCESS) {
+ bSuccess = true;
+ goto out;
+ }
+
+ iRet = forced_to_download_binary(data, KERNEL_CRASHED_BINARY);
+ if (iRet == SUCCESS)
+ bSuccess = true;
+ else
+ bSuccess = false;
+out:
+ return sprintf(buf, "%s\n", (bSuccess ? "OK" : "NG"));
+}
+
+ssize_t mcu_update_ums_bin_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ bool bSuccess = false;
+ int iRet = 0;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ ssp_dbg("[SSP]: %s - mcu binany update!\n", __func__);
+
+ iRet = forced_to_download_binary(data, UMS_BINARY);
+ if (iRet == SUCCESS)
+ bSuccess = true;
+ else
+ bSuccess = false;
+
+ return sprintf(buf, "%s\n", (bSuccess ? "OK" : "NG"));
+}
+
+ssize_t mcu_reset_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ reset_mcu(data);
+
+ return sprintf(buf, "OK\n");
+}
+
+ssize_t mcu_factorytest_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+ char chTempBuf[2] = {0, 10};
+ int iRet = 0;
+
+ if (sysfs_streq(buf, "1")) {
+ data->uFactorydataReady = 0;
+ memset(data->uFactorydata, 0, sizeof(char) * FACTORY_DATA_MAX);
+
+ data->bMcuIRQTestSuccessed = false;
+ data->uTimeOutCnt = 0;
+
+ iRet = send_instruction(data, FACTORY_MODE,
+ MCU_FACTORY, chTempBuf, 2);
+ if (data->uTimeOutCnt == 0)
+ data->bMcuIRQTestSuccessed = true;
+ } else {
+ pr_err("[SSP]: %s - invalid value %d\n", __func__, *buf);
+ return -EINVAL;
+ }
+
+ ssp_dbg("[SSP]: MCU Factory Test Start! - %d\n", iRet);
+
+ return size;
+}
+
+ssize_t mcu_factorytest_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ bool bMcuTestSuccessed = false;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ if (data->bSspShutdown == true) {
+ ssp_dbg("[SSP]: %s - MCU Bin is crashed\n", __func__);
+ return sprintf(buf, "NG,NG,NG\n");
+ }
+
+ if (data->uFactorydataReady & (1 << MCU_FACTORY)) {
+ ssp_dbg("[SSP] MCU Factory Test Data : %u, %u, %u, %u, %u\n",
+ data->uFactorydata[0], data->uFactorydata[1],
+ data->uFactorydata[2], data->uFactorydata[3],
+ data->uFactorydata[4]);
+
+ /* system clock, RTC, I2C Master, I2C Slave, externel pin */
+ if ((data->uFactorydata[0] == SUCCESS)
+ && (data->uFactorydata[1] == SUCCESS)
+ && (data->uFactorydata[2] == SUCCESS)
+ && (data->uFactorydata[3] == SUCCESS)
+ && (data->uFactorydata[4] == SUCCESS))
+ bMcuTestSuccessed = true;
+ } else {
+ pr_err("[SSP]: %s - The Sensorhub is not ready %u\n", __func__,
+ data->uFactorydataReady);
+ }
+
+ ssp_dbg("[SSP]: MCU Factory Test Result - %s, %s, %s\n", MODEL_NAME,
+ (data->bMcuIRQTestSuccessed ? "OK" : "NG"),
+ (bMcuTestSuccessed ? "OK" : "NG"));
+
+ return sprintf(buf, "%s,%s,%s\n", MODEL_NAME,
+ (data->bMcuIRQTestSuccessed ? "OK" : "NG"),
+ (bMcuTestSuccessed ? "OK" : "NG"));
+}
+
+ssize_t mcu_sleep_factorytest_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+ char chTempBuf[2] = {0, 10};
+ int iRet = 0;
+
+ if (sysfs_streq(buf, "1")) {
+ data->uFactorydataReady = 0;
+ memset(data->uFactorydata, 0, sizeof(char) * FACTORY_DATA_MAX);
+
+ iRet = send_instruction(data, FACTORY_MODE,
+ MCU_SLEEP_FACTORY, chTempBuf, 2);
+ } else {
+ pr_err("[SSP]: %s - invalid value %d\n", __func__, *buf);
+ return -EINVAL;
+ }
+
+ ssp_dbg("[SSP]: MCU Sleep Factory Test Start! - %d\n", iRet);
+
+ return size;
+}
+
+ssize_t mcu_sleep_factorytest_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int iDataIdx, iSensorData = 0;
+ struct ssp_data *data = dev_get_drvdata(dev);
+ struct sensor_value fsb[SENSOR_MAX];
+
+ if (!(data->uFactorydataReady & (1 << MCU_SLEEP_FACTORY))) {
+ pr_err("[SSP]: %s - The Sensorhub is not ready\n", __func__);
+ goto exit;
+ }
+
+ for (iDataIdx = 0; iDataIdx < FACTORY_DATA_MAX;) {
+ iSensorData = (int)data->uFactorydata[iDataIdx++];
+
+ if ((iSensorData < 0) ||
+ (iSensorData >= (SENSOR_MAX - 1))) {
+ pr_err("[SSP]: %s - Mcu data frame error %d\n",
+ __func__, iSensorData);
+ goto exit;
+ }
+
+ data->get_sensor_data[iSensorData]((char *)data->uFactorydata,
+ &iDataIdx, &(fsb[iSensorData]));
+ }
+
+ convert_acc_data(&fsb[ACCELEROMETER_SENSOR].x);
+ convert_acc_data(&fsb[ACCELEROMETER_SENSOR].y);
+ convert_acc_data(&fsb[ACCELEROMETER_SENSOR].z);
+
+ fsb[ACCELEROMETER_SENSOR].x -= data->accelcal.x;
+ fsb[ACCELEROMETER_SENSOR].y -= data->accelcal.y;
+ fsb[ACCELEROMETER_SENSOR].z -= data->accelcal.z;
+
+ fsb[GYROSCOPE_SENSOR].x -= data->gyrocal.x;
+ fsb[GYROSCOPE_SENSOR].y -= data->gyrocal.y;
+ fsb[GYROSCOPE_SENSOR].z -= data->gyrocal.z;
+
+ fsb[PRESSURE_SENSOR].pressure[0] -= data->iPressureCal;
+
+exit:
+ ssp_dbg("[SSP]: %s Result\n"
+ "accel %d,%d,%d\n"
+ "gyro %d,%d,%d\n"
+ "mag %d,%d,%d\n"
+ "baro %d,%d\n"
+ "ges %d,%d,%d,%d\n"
+ "prox %u,%u\n"
+ "temp %d,%d,%d\n"
+ "light %u,%u,%u,%u\n", __func__,
+ fsb[ACCELEROMETER_SENSOR].x, fsb[ACCELEROMETER_SENSOR].y,
+ fsb[ACCELEROMETER_SENSOR].z, fsb[GYROSCOPE_SENSOR].x,
+ fsb[GYROSCOPE_SENSOR].y, fsb[GYROSCOPE_SENSOR].z,
+ fsb[GEOMAGNETIC_SENSOR].x, fsb[GEOMAGNETIC_SENSOR].y,
+ fsb[GEOMAGNETIC_SENSOR].z, fsb[PRESSURE_SENSOR].pressure[0],
+ fsb[PRESSURE_SENSOR].pressure[1],
+ fsb[GESTURE_SENSOR].data[0], fsb[GESTURE_SENSOR].data[1],
+ fsb[GESTURE_SENSOR].data[2], fsb[GESTURE_SENSOR].data[3],
+ fsb[PROXIMITY_SENSOR].prox[0], fsb[PROXIMITY_SENSOR].prox[1],
+ fsb[TEMPERATURE_HUMIDITY_SENSOR].data[0],
+ fsb[TEMPERATURE_HUMIDITY_SENSOR].data[1],
+ fsb[TEMPERATURE_HUMIDITY_SENSOR].data[2],
+ fsb[LIGHT_SENSOR].r, fsb[LIGHT_SENSOR].g, fsb[LIGHT_SENSOR].b,
+ fsb[LIGHT_SENSOR].w);
+
+ return sprintf(buf, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%u,"
+ "%u,%u,%u,%u,%d,%d,%d,%d,%d,%d\n",
+ fsb[ACCELEROMETER_SENSOR].x, fsb[ACCELEROMETER_SENSOR].y,
+ fsb[ACCELEROMETER_SENSOR].z, fsb[GYROSCOPE_SENSOR].x,
+ fsb[GYROSCOPE_SENSOR].y, fsb[GYROSCOPE_SENSOR].z,
+ fsb[GEOMAGNETIC_SENSOR].x, fsb[GEOMAGNETIC_SENSOR].y,
+ fsb[GEOMAGNETIC_SENSOR].z, fsb[PRESSURE_SENSOR].pressure[0],
+ fsb[PRESSURE_SENSOR].pressure[1], fsb[PROXIMITY_SENSOR].prox[1],
+ fsb[LIGHT_SENSOR].r, fsb[LIGHT_SENSOR].g, fsb[LIGHT_SENSOR].b,
+ fsb[LIGHT_SENSOR].w,
+ fsb[GESTURE_SENSOR].data[0], fsb[GESTURE_SENSOR].data[1],
+ fsb[GESTURE_SENSOR].data[2], fsb[GESTURE_SENSOR].data[3],
+ fsb[TEMPERATURE_HUMIDITY_SENSOR].data[0],
+ fsb[TEMPERATURE_HUMIDITY_SENSOR].data[1]);
+}
diff --git a/drivers/sensorhub/stm/factory/pressure_bmp182.c b/drivers/sensorhub/stm/factory/pressure_bmp182.c
new file mode 100755
index 0000000..a46266f
--- /dev/null
+++ b/drivers/sensorhub/stm/factory/pressure_bmp182.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2012, Samsung Electronics Co. Ltd. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "../ssp.h"
+
+#define VENDOR "BOSCH"
+#define CHIP_ID "BMP180"
+#define VENDOR_STM "STM"
+#define CHIP_ID_LPS25H "LPS25H"
+
+#define CALIBRATION_FILE_PATH "/efs/FactoryApp/baro_delta"
+
+#define PR_ABS_MAX 8388607 /* 24 bit 2'compl */
+#define PR_ABS_MIN -8388608
+
+/*************************************************************************/
+/* factory Sysfs */
+/*************************************************************************/
+
+static ssize_t sea_level_pressure_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+ int iNewSeaLevelPressure;
+
+ sscanf(buf, "%d", &iNewSeaLevelPressure);
+
+ if (iNewSeaLevelPressure == 0) {
+ pr_info("%s, our->temperature = 0\n", __func__);
+ iNewSeaLevelPressure = -1;
+ }
+
+ input_report_rel(data->pressure_input_dev, REL_DIAL,
+ iNewSeaLevelPressure);
+ input_sync(data->pressure_input_dev);
+
+ return size;
+}
+
+int pressure_open_calibration(struct ssp_data *data)
+{
+ char chBuf[10] = {0,};
+ int iErr = 0;
+ mm_segment_t old_fs;
+ struct file *cal_filp = NULL;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ cal_filp = filp_open(CALIBRATION_FILE_PATH, O_RDONLY, 0666);
+ if (IS_ERR(cal_filp)) {
+ iErr = PTR_ERR(cal_filp);
+ if (iErr != -ENOENT)
+ pr_err("[SSP]: %s - Can't open calibration file(%d)\n",
+ __func__, iErr);
+ set_fs(old_fs);
+ return iErr;
+ }
+ iErr = cal_filp->f_op->read(cal_filp,
+ chBuf, 10 * sizeof(char), &cal_filp->f_pos);
+ if (iErr < 0) {
+ pr_err("[SSP]: %s - Can't read the cal data from file (%d)\n",
+ __func__, iErr);
+ return iErr;
+ }
+ filp_close(cal_filp, current->files);
+ set_fs(old_fs);
+
+ iErr = kstrtoint(chBuf, 10, &data->iPressureCal);
+ if (iErr < 0) {
+ pr_err("[SSP]: %s - kstrtoint failed. %d", __func__, iErr);
+ return iErr;
+ }
+
+ ssp_dbg("[SSP]: open barometer calibration %d\n", data->iPressureCal);
+
+ if (data->iPressureCal < PR_ABS_MIN || data->iPressureCal > PR_ABS_MAX)
+ pr_err("[SSP]: %s - wrong offset value!!!\n", __func__);
+
+ return iErr;
+}
+
+static ssize_t pressure_cabratioin_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+ int iPressureCal = 0, iErr = 0;
+
+ iErr = kstrtoint(buf, 10, &iPressureCal);
+ if (iErr < 0) {
+ pr_err("[SSP]: %s - kstrtoint failed.(%d)", __func__, iErr);
+ return iErr;
+ }
+
+ if (iPressureCal < PR_ABS_MIN || iPressureCal > PR_ABS_MAX)
+ return -EINVAL;
+
+ data->iPressureCal = (s32)iPressureCal;
+
+ return size;
+}
+
+static ssize_t pressure_cabratioin_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ pressure_open_calibration(data);
+
+ return sprintf(buf, "%d\n", data->iPressureCal);
+}
+
+static ssize_t eeprom_check_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ bool bSuccess = false;
+ char chTempBuf[2] = {0, 10};
+ int iRet, iDelayCnt = 0;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ data->uFactorydataReady = 0;
+ memset(data->uFactorydata, 0, sizeof(char) * FACTORY_DATA_MAX);
+
+ iRet = send_instruction(data, FACTORY_MODE, PRESSURE_FACTORY,
+ chTempBuf, 2);
+
+ while (!(data->uFactorydataReady & (1 << PRESSURE_FACTORY))
+ && (iDelayCnt++ < 150)
+ && (iRet == SUCCESS))
+ msleep(20);
+
+ if ((iDelayCnt >= 150) || (iRet != SUCCESS)) {
+ pr_err("[SSP]: %s - Pressure Selftest Timeout!!\n",
+ __func__);
+ goto exit;
+ }
+
+ mdelay(5);
+
+ bSuccess = (bool)(!!data->uFactorydata[0]);
+ ssp_dbg("[SSP]: %s - %u\n", __func__, bSuccess);
+
+exit:
+ return snprintf(buf, PAGE_SIZE, "%d", bSuccess);
+}
+
+/* sysfs for vendor & name */
+static ssize_t pressure_vendor_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", VENDOR);
+}
+
+static ssize_t pressure_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", CHIP_ID);
+}
+
+static DEVICE_ATTR(vendor, S_IRUGO, pressure_vendor_show, NULL);
+static DEVICE_ATTR(name, S_IRUGO, pressure_name_show, NULL);
+static DEVICE_ATTR(eeprom_check, S_IRUGO, eeprom_check_show, NULL);
+static DEVICE_ATTR(calibration, S_IRUGO | S_IWUSR | S_IWGRP,
+ pressure_cabratioin_show, pressure_cabratioin_store);
+static DEVICE_ATTR(sea_level_pressure, S_IRUGO | S_IWUSR | S_IWGRP,
+ NULL, sea_level_pressure_store);
+
+static struct device_attribute *pressure_attrs[] = {
+ &dev_attr_vendor,
+ &dev_attr_name,
+ &dev_attr_calibration,
+ &dev_attr_sea_level_pressure,
+ &dev_attr_eeprom_check,
+ NULL,
+};
+
+void initialize_pressure_factorytest(struct ssp_data *data)
+{
+ sensors_register(data->prs_device, data, pressure_attrs,
+ "barometer_sensor");
+}
+
+void remove_pressure_factorytest(struct ssp_data *data)
+{
+ sensors_unregister(data->prs_device, pressure_attrs);
+}
diff --git a/drivers/sensorhub/stm/factory/prox_max88920.c b/drivers/sensorhub/stm/factory/prox_max88920.c
new file mode 100755
index 0000000..84d4fd5
--- /dev/null
+++ b/drivers/sensorhub/stm/factory/prox_max88920.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright (C) 2012, Samsung Electronics Co. Ltd. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "../ssp.h"
+
+#define VENDOR "MAXIM"
+#define CHIP_ID "MAX88920"
+
+#define CANCELATION_FILE_PATH "/efs/prox_cal"
+#define LCD_LDI_FILE_PATH "/sys/class/lcd/panel/window_type"
+
+#define LINE_1 '4'
+#define LINE_2 '2'
+
+#define LDI_OTHERS '0'
+#define LDI_GRAY '1'
+#define LDI_WHITE '2'
+
+#define DEFUALT_HIGH_THRESHOLD 60
+#define DEFUALT_LOW_THRESHOLD 45
+#define TBD_HIGH_THRESHOLD 65
+#define TBD_LOW_THRESHOLD 50
+#define WHITE_HIGH_THRESHOLD 70
+#define WHITE_LOW_THRESHOLD 55
+/*************************************************************************/
+/* factory Sysfs */
+/*************************************************************************/
+
+static ssize_t prox_vendor_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", VENDOR);
+}
+
+static ssize_t prox_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", CHIP_ID);
+}
+
+static ssize_t proximity_avg_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n",
+ data->buf[PROXIMITY_RAW].prox[1],
+ data->buf[PROXIMITY_RAW].prox[2],
+ data->buf[PROXIMITY_RAW].prox[3]);
+}
+
+static ssize_t proximity_avg_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ char chTempbuf[2] = { 1, 20};
+ int iRet;
+ int64_t dEnable;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ iRet = kstrtoll(buf, 10, &dEnable);
+ if (iRet < 0)
+ return iRet;
+
+ if (dEnable) {
+ send_instruction(data, ADD_SENSOR, PROXIMITY_RAW, chTempbuf, 2);
+ data->bProximityRawEnabled = true;
+ } else {
+ send_instruction(data, REMOVE_SENSOR, PROXIMITY_RAW,
+ chTempbuf, 2);
+ data->bProximityRawEnabled = false;
+ }
+
+ return size;
+}
+
+static unsigned char get_proximity_rawdata(struct ssp_data *data)
+{
+ unsigned char uRowdata = 0;
+ char chTempbuf[2] = { 1, 20};
+
+ if (data->bProximityRawEnabled == false) {
+ send_instruction(data, ADD_SENSOR, PROXIMITY_RAW, chTempbuf, 2);
+ msleep(200);
+ uRowdata = data->buf[PROXIMITY_RAW].prox[0];
+ send_instruction(data, REMOVE_SENSOR, PROXIMITY_RAW,
+ chTempbuf, 2);
+ } else {
+ uRowdata = data->buf[PROXIMITY_RAW].prox[0];
+ }
+
+ return uRowdata;
+}
+
+static ssize_t proximity_state_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", get_proximity_rawdata(data));
+}
+
+static ssize_t proximity_raw_data_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%u\n", get_proximity_rawdata(data));
+}
+
+static int get_proximity_threshold(struct ssp_data *data)
+{
+ if (data->uProxCanc <= (data->uProxLoThresh_default >> 1))
+ return FAIL;
+
+ data->uProxHiThresh = data->uProxHiThresh_default
+ + (data->uProxCanc - (data->uProxLoThresh_default >> 1));
+ data->uProxLoThresh = data->uProxLoThresh_default
+ + (data->uProxCanc - (data->uProxLoThresh_default >> 1));
+
+ return SUCCESS;
+}
+
+static void change_proximity_default_threshold(struct ssp_data *data)
+{
+ switch (data->chLcdLdi[1]) {
+ case LDI_GRAY:
+ data->uProxHiThresh_default = TBD_HIGH_THRESHOLD;
+ data->uProxLoThresh_default = TBD_LOW_THRESHOLD;
+ break;
+ case LDI_WHITE:
+ data->uProxHiThresh_default = WHITE_HIGH_THRESHOLD;
+ data->uProxLoThresh_default = WHITE_LOW_THRESHOLD;
+ break;
+ case LDI_OTHERS:
+ data->uProxHiThresh_default = DEFUALT_HIGH_THRESHOLD;
+ data->uProxLoThresh_default = DEFUALT_LOW_THRESHOLD;
+ break;
+ default:
+ data->uProxHiThresh_default = DEFUALT_HIGH_THRESHOLD;
+ data->uProxLoThresh_default = DEFUALT_LOW_THRESHOLD;
+ break;
+ }
+ data->uProxHiThresh = data->uProxHiThresh_default;
+ data->uProxLoThresh = data->uProxLoThresh_default;
+}
+
+int proximity_open_lcd_ldi(struct ssp_data *data)
+{
+ int iRet = 0;
+ mm_segment_t old_fs;
+ struct file *cancel_filp = NULL;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ cancel_filp = filp_open(LCD_LDI_FILE_PATH, O_RDONLY, 0666);
+ if (IS_ERR(cancel_filp)) {
+ iRet = PTR_ERR(cancel_filp);
+ if (iRet != -ENOENT)
+ pr_err("[SSP]: %s - Can't open lcd ldi file\n",
+ __func__);
+ set_fs(old_fs);
+ data->chLcdLdi[0] = 0;
+ data->chLcdLdi[1] = 0;
+ goto exit;
+ }
+
+ iRet = cancel_filp->f_op->read(cancel_filp,
+ (u8 *)data->chLcdLdi, sizeof(u8) * 2, &cancel_filp->f_pos);
+ if (iRet != (sizeof(u8) * 2)) {
+ pr_err("[SSP]: %s - Can't read the lcd ldi data\n", __func__);
+ iRet = -EIO;
+ }
+
+ ssp_dbg("[SSP]: %s - %c%c\n", __func__,
+ data->chLcdLdi[0], data->chLcdLdi[1]);
+
+ filp_close(cancel_filp, current->files);
+ set_fs(old_fs);
+
+exit:
+ change_proximity_default_threshold(data);
+ return iRet;
+}
+
+int proximity_open_calibration(struct ssp_data *data)
+{
+ int iRet = 0;
+ mm_segment_t old_fs;
+ struct file *cancel_filp = NULL;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ cancel_filp = filp_open(CANCELATION_FILE_PATH, O_RDONLY, 0666);
+ if (IS_ERR(cancel_filp)) {
+ iRet = PTR_ERR(cancel_filp);
+ if (iRet != -ENOENT)
+ pr_err("[SSP]: %s - Can't open cancelation file\n",
+ __func__);
+ set_fs(old_fs);
+ goto exit;
+ }
+
+ iRet = cancel_filp->f_op->read(cancel_filp,
+ (u8 *)&data->uProxCanc, sizeof(u8), &cancel_filp->f_pos);
+ if (iRet != sizeof(u8)) {
+ pr_err("[SSP]: %s - Can't read the cancel data\n", __func__);
+ iRet = -EIO;
+ }
+
+ if (data->uProxCanc != 0) /* If there is an offset cal data. */
+ get_proximity_threshold(data);
+
+ pr_info("%s: proximity ps_canc = %d, ps_thresh hi - %d lo - %d\n",
+ __func__, data->uProxCanc, data->uProxHiThresh,
+ data->uProxLoThresh);
+
+ filp_close(cancel_filp, current->files);
+ set_fs(old_fs);
+
+exit:
+ set_proximity_threshold(data, data->uProxHiThresh, data->uProxLoThresh);
+
+ return iRet;
+}
+
+static int proximity_store_cancelation(struct ssp_data *data, int iCalCMD)
+{
+ int iRet = 0;
+ mm_segment_t old_fs;
+ struct file *cancel_filp = NULL;
+
+ if (iCalCMD) {
+ data->uProxCanc = get_proximity_rawdata(data);
+ get_proximity_threshold(data);
+ } else {
+ data->uProxHiThresh = data->uProxHiThresh_default;
+ data->uProxLoThresh = data->uProxLoThresh_default;
+ data->uProxCanc = 0;
+ }
+
+ set_proximity_threshold(data, data->uProxHiThresh, data->uProxLoThresh);
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ cancel_filp = filp_open(CANCELATION_FILE_PATH,
+ O_CREAT | O_TRUNC | O_WRONLY | O_SYNC, 0666);
+ if (IS_ERR(cancel_filp)) {
+ pr_err("%s: Can't open cancelation file\n", __func__);
+ set_fs(old_fs);
+ iRet = PTR_ERR(cancel_filp);
+ return iRet;
+ }
+
+ iRet = cancel_filp->f_op->write(cancel_filp, (u8 *)&data->uProxCanc,
+ sizeof(u8), &cancel_filp->f_pos);
+ if (iRet != sizeof(u8)) {
+ pr_err("%s: Can't write the cancel data to file\n", __func__);
+ iRet = -EIO;
+ }
+
+ filp_close(cancel_filp, current->files);
+ set_fs(old_fs);
+
+ return iRet;
+}
+
+static ssize_t proximity_cancel_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+ unsigned char uProxCanc = data->uProxCanc;
+
+ if (uProxCanc > (data->uProxLoThresh_default >> 1))
+ uProxCanc = uProxCanc - (data->uProxLoThresh_default >> 1);
+ else
+ uProxCanc = 0;
+
+ ssp_dbg("[SSP]: uProxThresh : hi : %u lo : %u, uProxCanc = %u\n",
+ data->uProxHiThresh, data->uProxLoThresh, uProxCanc);
+
+ return sprintf(buf, "%u,%u,%u\n", uProxCanc, data->uProxHiThresh,
+ data->uProxLoThresh);
+}
+
+static ssize_t proximity_cancel_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ int iCalCMD = 0, iRet = 0;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ if (sysfs_streq(buf, "1")) /* calibrate cancelation value */
+ iCalCMD = 1;
+ else if (sysfs_streq(buf, "0")) /* reset cancelation value */
+ iCalCMD = 0;
+ else {
+ pr_debug("%s: invalid value %d\n", __func__, *buf);
+ return -EINVAL;
+ }
+
+ iRet = proximity_store_cancelation(data, iCalCMD);
+ if (iRet < 0) {
+ pr_err("[SSP]: - %s proximity_store_cancelation() failed\n",
+ __func__);
+ return iRet;
+ }
+
+ ssp_dbg("[SSP]: %s - %u\n", __func__, iCalCMD);
+ return size;
+}
+
+static ssize_t proximity_thresh_high_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ ssp_dbg("[SSP]: uProxThresh = hi - %u, lo - %u\n",
+ data->uProxHiThresh, data->uProxLoThresh);
+
+ return sprintf(buf, "%u,%u\n", data->uProxHiThresh,
+ data->uProxLoThresh);
+}
+
+static ssize_t proximity_thresh_high_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ u8 uNewThresh;
+ int iRet = 0;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ iRet = kstrtou8(buf, 10, &uNewThresh);
+ if (iRet < 0)
+ pr_err("[SSP]: %s - kstrtoint failed.(%d)\n", __func__, iRet);
+ else {
+ data->uProxHiThresh = uNewThresh;
+ set_proximity_threshold(data, data->uProxHiThresh,
+ data->uProxLoThresh);
+ }
+
+ ssp_dbg("[SSP]: %s - new prox threshold : hi - %u, lo - %u\n",
+ __func__, data->uProxHiThresh, data->uProxLoThresh);
+
+ return size;
+}
+
+static ssize_t proximity_thresh_low_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ ssp_dbg("[SSP]: uProxThresh = hi - %u, lo - %u\n",
+ data->uProxHiThresh, data->uProxLoThresh);
+
+ return sprintf(buf, "%u,%u\n", data->uProxHiThresh,
+ data->uProxLoThresh);
+}
+
+static ssize_t proximity_thresh_low_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ u8 uNewThresh;
+ int iRet = 0;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ iRet = kstrtou8(buf, 10, &uNewThresh);
+ if (iRet < 0)
+ pr_err("[SSP]: %s - kstrtoint failed.(%d)\n", __func__, iRet);
+ else {
+ data->uProxLoThresh = uNewThresh;
+ set_proximity_threshold(data, data->uProxHiThresh,
+ data->uProxLoThresh);
+ }
+
+ ssp_dbg("[SSP]: %s - new prox threshold : hi - %u, lo - %u\n",
+ __func__, data->uProxHiThresh, data->uProxLoThresh);
+
+ return size;
+}
+
+static ssize_t barcode_emul_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n", data->bBarcodeEnabled);
+}
+
+static ssize_t barcode_emul_enable_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ int iRet;
+ int64_t dEnable;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ iRet = kstrtoll(buf, 10, &dEnable);
+ if (iRet < 0)
+ return iRet;
+
+ if (dEnable)
+ set_proximity_barcode_enable(data, true);
+ else
+ set_proximity_barcode_enable(data, false);
+
+ return size;
+}
+
+static DEVICE_ATTR(vendor, S_IRUGO, prox_vendor_show, NULL);
+static DEVICE_ATTR(name, S_IRUGO, prox_name_show, NULL);
+static DEVICE_ATTR(state, S_IRUGO, proximity_state_show, NULL);
+static DEVICE_ATTR(raw_data, S_IRUGO, proximity_raw_data_show, NULL);
+static DEVICE_ATTR(barcode_emul_en, S_IRUGO | S_IWUSR | S_IWGRP,
+ barcode_emul_enable_show, barcode_emul_enable_store);
+static DEVICE_ATTR(prox_avg, S_IRUGO | S_IWUSR | S_IWGRP,
+ proximity_avg_show, proximity_avg_store);
+static DEVICE_ATTR(prox_cal, S_IRUGO | S_IWUSR | S_IWGRP,
+ proximity_cancel_show, proximity_cancel_store);
+static DEVICE_ATTR(thresh_high, S_IRUGO | S_IWUSR | S_IWGRP,
+ proximity_thresh_high_show, proximity_thresh_high_store);
+static DEVICE_ATTR(thresh_low, S_IRUGO | S_IWUSR | S_IWGRP,
+ proximity_thresh_low_show, proximity_thresh_low_store);
+
+static struct device_attribute *prox_attrs[] = {
+ &dev_attr_vendor,
+ &dev_attr_name,
+ &dev_attr_state,
+ &dev_attr_raw_data,
+ &dev_attr_prox_avg,
+ &dev_attr_prox_cal,
+ &dev_attr_thresh_high,
+ &dev_attr_thresh_low,
+ &dev_attr_barcode_emul_en,
+ NULL,
+};
+
+void initialize_prox_factorytest(struct ssp_data *data)
+{
+ sensors_register(data->prox_device, data,
+ prox_attrs, "proximity_sensor");
+}
+
+void remove_prox_factorytest(struct ssp_data *data)
+{
+ sensors_unregister(data->prox_device, prox_attrs);
+}
diff --git a/drivers/sensorhub/stm/factory/temphumidity_shtc1.c b/drivers/sensorhub/stm/factory/temphumidity_shtc1.c
new file mode 100755
index 0000000..45e0ea5
--- /dev/null
+++ b/drivers/sensorhub/stm/factory/temphumidity_shtc1.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2012, Samsung Electronics Co. Ltd. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "../ssp.h"
+#include <linux/platform_device.h>
+#include <plat/adc.h>
+
+/*************************************************************************/
+/* factory Sysfs */
+/*************************************************************************/
+
+#define VENDOR "SENSIRION"
+#define CHIP_ID "SHTC1"
+
+#define CP_THM_ADC_SAMPLING_CNT 7
+//#define DONE_CAL 3
+
+static int cp_thm_get_adc_data(struct ssp_data *data)
+{
+ int adc_data;
+ int adc_max = 0;
+ int adc_min = 0;
+ int adc_total = 0;
+ int i;
+ int err_value;
+
+ for (i = 0; i < CP_THM_ADC_SAMPLING_CNT; i++) {
+ mutex_lock(&data->cp_temp_adc_lock);
+ if (data->adc_client)
+ adc_data = s3c_adc_read(data->adc_client, data->cp_thm_adc_channel);
+ else
+ adc_data = 0;
+ mutex_unlock(&data->cp_temp_adc_lock);
+
+ if (adc_data < 0) {
+ pr_err("[SSP] : %s err(%d) returned, skip read\n",
+ __func__, adc_data);
+ err_value = adc_data;
+ goto err;
+ }
+
+ if (i != 0) {
+ if (adc_data > adc_max)
+ adc_max = adc_data;
+ else if (adc_data < adc_min)
+ adc_min = adc_data;
+ } else {
+ adc_max = adc_data;
+ adc_min = adc_data;
+ }
+ adc_total += adc_data;
+ }
+
+ return (adc_total - adc_max - adc_min) / (CP_THM_ADC_SAMPLING_CNT - 2);
+err:
+ return err_value;
+}
+
+static int convert_adc_to_temp(struct ssp_data *data, unsigned int adc)
+{
+ u8 low = 0, mid = 0;
+ u8 high;
+
+ if (!data->cp_thm_adc_table || !data->cp_thm_adc_arr_size) {
+ /* using fake temp */
+ return 300;
+ }
+
+ high = data->cp_thm_adc_arr_size - 1;
+
+ while (low <= high) {
+ mid = (low + high) / 2;
+ if (data->cp_thm_adc_table[mid].adc > adc)
+ high = mid - 1;
+ else if (data->cp_thm_adc_table[mid].adc < adc)
+ low = mid + 1;
+ else
+ break;
+ }
+ return data->cp_thm_adc_table[mid].temperature;
+}
+
+static ssize_t temphumidity_vendor_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", VENDOR);
+}
+
+static ssize_t temphumidity_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", CHIP_ID);
+}
+
+static ssize_t engine_version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ pr_err("[SSP] %s - engine_ver = %s_%s\n",
+ __func__, CONFIG_SENSORS_SSP_SHTC1_VER, data->comp_engine_ver);
+
+ return sprintf(buf, "%s_%s\n",
+ CONFIG_SENSORS_SSP_SHTC1_VER, data->comp_engine_ver);
+}
+
+ssize_t engine_version_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ kfree(data->comp_engine_ver);
+ data->comp_engine_ver =
+ kzalloc(((strlen(buf)+1) * sizeof(char)), GFP_KERNEL);
+ strncpy(data->comp_engine_ver, buf, strlen(buf)+1);
+ pr_err("[SSP] %s - engine_ver = %s, %s\n",
+ __func__, data->comp_engine_ver, buf);
+
+ return size;
+}
+
+static ssize_t pam_adc_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+ int cp_thm_adc = 0;
+
+ if (data->bSspShutdown == false)
+ cp_thm_adc = cp_thm_get_adc_data(data);
+ else
+ pr_info("[SSP] : %s, device is shutting down", __func__);
+
+ return sprintf(buf, "%d\n", cp_thm_adc);
+}
+
+static ssize_t pam_temp_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+ int adc, temp;
+
+#if defined(CONFIG_MACH_J_CHN_CTC)
+ printk("[SSP] pam_temp_show : %d", data->ap_rev);
+ if((data->ap_rev) < 7) /* HW REV12 == 7*/
+ temp = -990;
+ else
+ {
+#endif
+ adc = cp_thm_get_adc_data(data);
+ if (adc < 0) {
+ pr_err("[SSP] : %s, reading adc failed.(%d)\n", __func__, adc);
+ temp = adc;
+ } else
+ temp = convert_adc_to_temp(data, adc);
+
+#if defined(CONFIG_MACH_J_CHN_CTC)
+ }
+#endif
+
+ return sprintf(buf, "%d\n", temp);
+}
+
+static ssize_t temphumidity_crc_check(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ char chTempBuf[2] = {0, 10};
+ int iDelayCnt = 0, iRet;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ data->uFactorydata[0] = 0xff;
+ data->uFactorydataReady = 0;
+ iRet = send_instruction(data, FACTORY_MODE,
+ TEMPHUMIDITY_CRC_FACTORY, chTempBuf, 2);
+
+ while (!(data->uFactorydataReady &
+ (1 << TEMPHUMIDITY_CRC_FACTORY))
+ && (iDelayCnt++ < 50)
+ && (iRet == SUCCESS))
+ msleep(20);
+
+ if ((iDelayCnt >= 50) || (iRet != SUCCESS)) {
+ pr_err("[SSP]: %s - Temphumidity check crc Timeout!! %d\n",
+ __func__, iRet);
+ goto exit;
+ }
+
+ mdelay(5);
+
+ pr_info("[SSP] : %s -Check_CRC : %d\n", __func__,
+ data->uFactorydata[0]);
+
+exit:
+ if (data->uFactorydata[0] == 1)
+ return sprintf(buf, "%s\n", "OK");
+ else if (data->uFactorydata[0] == 2)
+ return sprintf(buf, "%s\n","NG_NC");
+ else
+ return sprintf(buf, "%s\n","NG");
+}
+
+static ssize_t temphumidity_compengine_reset(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ data->comp_engine_cmd = SHTC1_CMD_RESET;
+
+ return sprintf(buf, "%d\n", 1);
+}
+/*
+ssize_t temphumidity_send_accuracy(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+ u8 accuracy;
+
+ if (kstrtou8(buf, 10, &accuracy) < 0) {
+ pr_err("[SSP] %s - read buf is fail(%s)\n", __func__, buf);
+ return size;
+ }
+
+ if (accuracy == DONE_CAL)
+ ssp_send_cmd(data, MSG2SSP_AP_TEMPHUMIDITY_CAL_DONE);
+ pr_info("[SSP] %s - accuracy = %d\n", __func__, accuracy);
+
+ return size;
+}
+*/
+static DEVICE_ATTR(name, S_IRUGO, temphumidity_name_show, NULL);
+static DEVICE_ATTR(vendor, S_IRUGO, temphumidity_vendor_show, NULL);
+static DEVICE_ATTR(engine_ver, S_IRUGO | S_IWUSR | S_IWGRP,
+ engine_version_show, engine_version_store);
+static DEVICE_ATTR(cp_thm, S_IRUGO,
+ pam_adc_show, NULL);
+static DEVICE_ATTR(cp_temperature, S_IRUGO,
+ pam_temp_show, NULL);
+static DEVICE_ATTR(crc_check, S_IRUGO,
+ temphumidity_crc_check, NULL);
+static DEVICE_ATTR(reset, S_IRUGO,
+ temphumidity_compengine_reset, NULL);
+/*static DEVICE_ATTR(send_accuracy, S_IWUSR | S_IWGRP,
+ NULL, temphumidity_send_accuracy);*/
+
+static struct device_attribute *temphumidity_attrs[] = {
+ &dev_attr_name,
+ &dev_attr_vendor,
+ &dev_attr_engine_ver,
+ &dev_attr_cp_thm,
+ &dev_attr_cp_temperature,
+ &dev_attr_crc_check,
+ &dev_attr_reset,
+// &dev_attr_send_accuracy,
+ NULL,
+};
+
+void initialize_temphumidity_factorytest(struct ssp_data *data)
+{
+ /* alloc platform device for adc client */
+ data->pdev_pam_temp = platform_device_alloc("pam-temp-adc", -1);
+ if (!data->pdev_pam_temp)
+ pr_err("%s: could not allocation pam-temp-adc\n", __func__);
+
+ data->adc_client = s3c_adc_register(data->pdev_pam_temp, NULL, NULL, 0);
+ if (IS_ERR(data->adc_client))
+ pr_err("%s, fail to register pam-temp-adc(%ld)\n",
+ __func__, IS_ERR(data->adc_client));
+
+ sensors_register(data->temphumidity_device,
+ data, temphumidity_attrs, "temphumidity_sensor");
+}
+
+void remove_temphumidity_factorytest(struct ssp_data *data)
+{
+ if (data->adc_client)
+ s3c_adc_release(data->adc_client);
+ if (data->pdev_pam_temp)
+ platform_device_put(data->pdev_pam_temp);
+ sensors_unregister(data->temphumidity_device, temphumidity_attrs);
+ kfree(data->comp_engine_ver);
+}