aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sensorhub/factory
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sensorhub/factory')
-rw-r--r--drivers/sensorhub/factory/accel_lsm330.c300
-rw-r--r--drivers/sensorhub/factory/gyro_lsm330.c307
-rw-r--r--drivers/sensorhub/factory/light_cm36651.c74
-rw-r--r--drivers/sensorhub/factory/magnetic_ak8963c.c221
-rw-r--r--drivers/sensorhub/factory/mcu_at32uc3l0128.c257
-rw-r--r--drivers/sensorhub/factory/pressure_bmp182.c190
-rw-r--r--drivers/sensorhub/factory/prox_cm36651.c373
7 files changed, 1722 insertions, 0 deletions
diff --git a/drivers/sensorhub/factory/accel_lsm330.c b/drivers/sensorhub/factory/accel_lsm330.c
new file mode 100644
index 0000000..71bec9e
--- /dev/null
+++ b/drivers/sensorhub/factory/accel_lsm330.c
@@ -0,0 +1,300 @@
+/*
+ * 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 "STM"
+#define CHIP_ID "LSM330"
+
+#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 - 1024);
+ 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);
+ } 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\n", __func__);
+
+ 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 = strict_strtoll(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;
+ }
+
+ 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)
+{
+ struct device *acc_device = NULL;
+
+ sensors_register(acc_device, data, acc_attrs, "accelerometer_sensor");
+}
diff --git a/drivers/sensorhub/factory/gyro_lsm330.c b/drivers/sensorhub/factory/gyro_lsm330.c
new file mode 100644
index 0000000..11b0ac4
--- /dev/null
+++ b/drivers/sensorhub/factory/gyro_lsm330.c
@@ -0,0 +1,307 @@
+/*
+ * 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 "STM"
+#define CHIP_ID "LSM330"
+
+#define CALIBRATION_FILE_PATH "/efs/gyro_cal_data"
+#define CALIBRATION_DATA_AMOUNT 20
+
+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);
+}
+
+static ssize_t gyro_get_temp(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ char chTempBuf[2] = { 0, 10}, chTemp = 0;
+ int iDelayCnt = 0, iRet = 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, 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;
+ }
+
+ chTemp = (char)data->uFactorydata[0];
+ ssp_dbg("[SSP]: %s - %d\n", __func__, chTemp);
+exit:
+ return sprintf(buf, "%d\n", chTemp);
+}
+
+static ssize_t gyro_selftest_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ char chTempBuf[2] = { 3, 200};
+ u8 uFifoPass = 2;
+ u8 uBypassPass = 2;
+ u8 uCalPass = 0;
+ s16 iNOST[3] = {0,}, iST[3] = {0,}, iCalData[3] = {0,};
+ int iZeroRateData[3] = {0,};
+ int iDelayCnt = 0, iRet = 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, 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;
+ }
+
+ 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]);
+
+ uCalPass = data->uFactorydata[24];
+ uFifoPass = data->uFactorydata[25];
+ uBypassPass = data->uFactorydata[26];
+
+ if (uFifoPass && uBypassPass && uCalPass)
+ save_gyro_caldata(data, iCalData);
+
+exit:
+ ssp_dbg("[SSP]: Gyro Selftest - %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],
+ uFifoPass & uBypassPass & uCalPass, uFifoPass, uCalPass);
+
+ return sprintf(buf, "%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],
+ uFifoPass & uBypassPass & uCalPass, uFifoPass, uCalPass);
+}
+
+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);
+
+ 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;
+ }
+
+ 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)
+{
+ struct device *gyro_device = NULL;
+
+ sensors_register(gyro_device, data, gyro_attrs, "gyro_sensor");
+}
diff --git a/drivers/sensorhub/factory/light_cm36651.c b/drivers/sensorhub/factory/light_cm36651.c
new file mode 100644
index 0000000..17ad68a
--- /dev/null
+++ b/drivers/sensorhub/factory/light_cm36651.c
@@ -0,0 +1,74 @@
+/*
+ * 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 "CM36651"
+
+/*************************************************************************/
+/* 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);
+}
+
+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)
+{
+ struct device *light_device = NULL;
+
+ sensors_register(light_device, data, light_attrs, "light_sensor");
+}
diff --git a/drivers/sensorhub/factory/magnetic_ak8963c.c b/drivers/sensorhub/factory/magnetic_ak8963c.c
new file mode 100644
index 0000000..4a72006
--- /dev/null
+++ b/drivers/sensorhub/factory/magnetic_ak8963c.c
@@ -0,0 +1,221 @@
+/*
+ * 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 "AKM"
+#define CHIP_ID "AK8963C"
+
+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 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[GEOMAGNETIC_SENSOR].x,
+ data->buf[GEOMAGNETIC_SENSOR].y,
+ data->buf[GEOMAGNETIC_SENSOR].z);
+}
+
+static ssize_t adc_data_read(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ bool bSuccess = false;
+ u8 chTempbuf[2] = {1, 20};
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ if (!(atomic_read(&data->aSensorEnable) & (1 << GEOMAGNETIC_SENSOR))) {
+ send_instruction(data, ADD_SENSOR, GEOMAGNETIC_SENSOR,
+ chTempbuf, 2);
+ msleep(200);
+ }
+
+ if ((data->buf[GEOMAGNETIC_SENSOR].x == 0) &&
+ (data->buf[GEOMAGNETIC_SENSOR].y == 0) &&
+ (data->buf[GEOMAGNETIC_SENSOR].z == 0))
+ bSuccess = false;
+ else
+ bSuccess = true;
+
+ 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__,
+ data->buf[GEOMAGNETIC_SENSOR].x,
+ data->buf[GEOMAGNETIC_SENSOR].y,
+ data->buf[GEOMAGNETIC_SENSOR].z);
+
+ return sprintf(buf, "%s,%d,%d,%d\n", (bSuccess ? "OK" : "NG"),
+ data->buf[GEOMAGNETIC_SENSOR].x,
+ data->buf[GEOMAGNETIC_SENSOR].y,
+ data->buf[GEOMAGNETIC_SENSOR].z);
+}
+
+static ssize_t magnetic_get_asa(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d,%d,%d\n", (s16)data->uFuseRomData[0],
+ (s16)data->uFuseRomData[1], (s16)data->uFuseRomData[2]);
+}
+
+static ssize_t magnetic_get_status(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ bool bSuccess;
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ if ((data->uFuseRomData[0] == 0) ||
+ (data->uFuseRomData[0] == 0xff) ||
+ (data->uFuseRomData[1] == 0) ||
+ (data->uFuseRomData[1] == 0xff) ||
+ (data->uFuseRomData[2] == 0) ||
+ (data->uFuseRomData[2] == 0xff))
+ bSuccess = false;
+ else
+ bSuccess = true;
+
+ return sprintf(buf, "%s,%u\n", (bSuccess ? "OK" : "NG"), bSuccess);
+}
+
+static ssize_t magnetic_get_selftest(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ bool bSelftestPassed = false;
+ s16 iSF_X = 0, iSF_Y = 0, iSF_Z = 0;
+ int iDelayCnt = 0, iRet = 0, iReties = 0;
+ char chTempBuf[2] = { 0, 10 };
+ 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!!\n", __func__);
+ goto exit;
+ }
+
+ iSF_X = (s16)((data->uFactorydata[0] << 8) + data->uFactorydata[1]);
+ iSF_Y = (s16)((data->uFactorydata[2] << 8) + data->uFactorydata[3]);
+ iSF_Z = (s16)((data->uFactorydata[4] << 8) + data->uFactorydata[5]);
+
+ iSF_X = (s16)(((int)iSF_X * ((int)data->uFuseRomData[0] + 128)) >> 8);
+ iSF_Y = (s16)(((int)iSF_Y * ((int)data->uFuseRomData[1] + 128)) >> 8);
+ iSF_Z = (s16)(((int)iSF_Z * ((int)data->uFuseRomData[2] + 128)) >> 8);
+
+ pr_info("[SSP] %s: self test x = %d, y = %d, z = %d\n",
+ __func__, iSF_X, iSF_Y, iSF_Z);
+ if ((iSF_X >= -200) && (iSF_X <= 200))
+ pr_info("[SSP] x passed self test, expect -200<=x<=200\n");
+ else
+ pr_info("[SSP] x failed self test, expect -200<=x<=200\n");
+ if ((iSF_Y >= -200) && (iSF_Y <= 200))
+ pr_info("[SSP] y passed self test, expect -200<=y<=200\n");
+ else
+ pr_info("[SSP] y failed self test, expect -200<=y<=200\n");
+ if ((iSF_Z >= -3200) && (iSF_Z <= -800))
+ pr_info("[SSP] z passed self test, expect -3200<=z<=-800\n");
+ else
+ pr_info("[SSP] z failed self test, expect -3200<=z<=-800\n");
+
+ if (((iSF_X >= -200) && (iSF_X <= 200)) &&
+ ((iSF_Y >= -200) && (iSF_Y <= 200)) &&
+ ((iSF_Z >= -3200) && (iSF_Z <= -800)))
+ bSelftestPassed = true;
+
+ if ((bSelftestPassed == false) && (iReties++ < 5))
+ goto reties;
+exit:
+ return sprintf(buf, "%u,%d,%d,%d\n",
+ bSelftestPassed, iSF_X, iSF_Y, iSF_Z);
+}
+
+static ssize_t magnetic_check_registers(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 uBuf[13] = {0,};
+
+ return sprintf(buf, "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u\n",
+ uBuf[0], uBuf[1], uBuf[2], uBuf[3], uBuf[4], uBuf[5],
+ uBuf[6], uBuf[7], uBuf[8], uBuf[9], uBuf[10], uBuf[11],
+ uBuf[12]);
+}
+
+static ssize_t magnetic_check_cntl(struct device *dev,
+ struct device_attribute *attr, char *strbuf)
+{
+ bool bSuccess = false;
+
+ return sprintf(strbuf, "%s,%d,%d,%d\n",
+ (!bSuccess ? "OK" : "NG"), 0, 0, 0);
+}
+
+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, raw_data_read, NULL);
+static DEVICE_ATTR(status, S_IRUGO, magnetic_get_status, NULL);
+static DEVICE_ATTR(adc, S_IRUGO, adc_data_read, NULL);
+static DEVICE_ATTR(dac, S_IRUGO, magnetic_check_cntl, NULL);
+static DEVICE_ATTR(selftest, S_IRUGO, magnetic_get_selftest, NULL);
+static DEVICE_ATTR(ak8963_asa, S_IRUGO, magnetic_get_asa, NULL);
+static DEVICE_ATTR(ak8963_chk_registers, S_IRUGO,
+ magnetic_check_registers, NULL);
+
+static struct device_attribute *mag_attrs[] = {
+ &dev_attr_name,
+ &dev_attr_vendor,
+ &dev_attr_adc,
+ &dev_attr_raw_data,
+ &dev_attr_status,
+ &dev_attr_selftest,
+ &dev_attr_ak8963_asa,
+ &dev_attr_ak8963_chk_registers,
+ &dev_attr_dac,
+ NULL,
+};
+
+void initialize_magnetic_factorytest(struct ssp_data *data)
+{
+ struct device *mag_device = NULL;
+
+ sensors_register(mag_device, data, mag_attrs, "magnetic_sensor");
+}
diff --git a/drivers/sensorhub/factory/mcu_at32uc3l0128.c b/drivers/sensorhub/factory/mcu_at32uc3l0128.c
new file mode 100644
index 0000000..f4549ac
--- /dev/null
+++ b/drivers/sensorhub/factory/mcu_at32uc3l0128.c
@@ -0,0 +1,257 @@
+/*
+ * 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 "AT32UC3L0128"
+
+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, "AT01120%u,AT01120%u\n", get_module_rev(),
+ data->uCurFirmRev);
+}
+
+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_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__);
+
+ disable_irq(data->iIrq);
+ disable_irq_wake(data->iIrq);
+
+ iRet = update_mcu_bin(data);
+ if (iRet < 0) {
+ ssp_dbg("[SSP]: %s - update_mcu_bin failed!\n", __func__);
+ goto exit;
+ }
+
+ iRet = initialize_mcu(data);
+ if (iRet < 0) {
+ ssp_dbg("[SSP]: %s - initialize_mcu failed!\n", __func__);
+ goto exit;
+ }
+
+ sync_sensor_state(data);
+
+ enable_irq(data->iIrq);
+ enable_irq_wake(data->iIrq);
+
+#ifdef CONFIG_SENSORS_SSP_SENSORHUB
+ ssp_report_sensorhub_notice(data, MSG2SSP_AP_STATUS_RESET);
+#endif
+
+ bSuccess = true;
+exit:
+ return sprintf(buf, "%s\n", (bSuccess ? "OK" : "NG"));
+}
+
+ssize_t mcu_update2_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__);
+
+ disable_irq(data->iIrq);
+ disable_irq_wake(data->iIrq);
+
+ iRet = update_crashed_mcu_bin(data);
+ if (iRet < 0) {
+ ssp_dbg("[SSP]: %s - update_mcu_bin failed!\n", __func__);
+ goto exit;
+ }
+
+ iRet = initialize_mcu(data);
+ if (iRet < 0) {
+ ssp_dbg("[SSP]: %s - initialize_mcu failed!\n", __func__);
+ goto exit;
+ }
+
+ enable_irq(data->iIrq);
+ enable_irq_wake(data->iIrq);
+
+ if (atomic_read(&data->aSensorEnable) > 0)
+ sync_sensor_state(data);
+
+ bSuccess = true;
+exit:
+ 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->bBinaryChashed == true)
+ 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\n", __func__);
+ }
+ 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);
+
+exit:
+ ssp_dbg("[SSP]: %s Result - "
+ "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%u,%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[PROXIMITY_SENSOR].prox[1],
+ 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\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);
+}
diff --git a/drivers/sensorhub/factory/pressure_bmp182.c b/drivers/sensorhub/factory/pressure_bmp182.c
new file mode 100644
index 0000000..b3d580a
--- /dev/null
+++ b/drivers/sensorhub/factory/pressure_bmp182.c
@@ -0,0 +1,190 @@
+/*
+ * 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 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;
+ }
+
+ 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)
+{
+ struct device *pressure_device = NULL;
+
+ sensors_register(pressure_device, data, pressure_attrs,
+ "barometer_sensor");
+}
diff --git a/drivers/sensorhub/factory/prox_cm36651.c b/drivers/sensorhub/factory/prox_cm36651.c
new file mode 100644
index 0000000..3963952
--- /dev/null
+++ b/drivers/sensorhub/factory/prox_cm36651.c
@@ -0,0 +1,373 @@
+/*
+ * 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 "CM36651"
+
+#define CANCELATION_FILE_PATH "/efs/prox_cal"
+#define LCD_LDI_FILE_PATH "/sys/class/lcd/panel/window_type"
+
+#define LINE_1 '6'
+#define LINE_1_LDI_OTHERS '4'
+#define LINE_1_LDI_GRAY '5'
+#define LINE_1_LDI_WHITE '6'
+
+#define LINE_2 '3'
+#define LINE_2_LDI_OTHERS '2'
+#define LINE_2_LDI_GRAY '3'
+#define LINE_2_LDI_WHITE '4'
+/*************************************************************************/
+/* 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 = strict_strtoll(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 void change_proximity_default_threshold(struct ssp_data *data)
+{
+ if (((data->chLcdLdi[0] == LINE_1)
+ && (data->chLcdLdi[1] == LINE_1_LDI_GRAY))
+ || ((data->chLcdLdi[0] == LINE_2)
+ && (data->chLcdLdi[1] == LINE_2_LDI_GRAY)))
+ data->uProxThresh = GRAY_OCTA_DEFAULT_THRESHOLD;
+ else if (((data->chLcdLdi[0] == LINE_1)
+ && (data->chLcdLdi[1] == LINE_1_LDI_WHITE))
+ || ((data->chLcdLdi[0] == LINE_2)
+ && (data->chLcdLdi[1] == LINE_2_LDI_WHITE)))
+ data->uProxThresh = WHITE_OCTA_DEFAULT_THRESHOLD;
+ else if (((data->chLcdLdi[0] == LINE_1)
+ && (data->chLcdLdi[1] == LINE_1_LDI_OTHERS))
+ || ((data->chLcdLdi[0] == LINE_2)
+ && (data->chLcdLdi[1] == LINE_2_LDI_OTHERS)))
+ data->uProxThresh = OTHERS_OCTA_DEFAULT_THRESHOLD;
+ else
+ data->uProxThresh = DEFAULT_THRESHOLD;
+}
+
+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 - 1st : %c\n", __func__, data->chLcdLdi[0]);
+ ssp_dbg("[SSP]: %s - 1st : %c\n", __func__, 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. */
+ data->uProxThresh = CANCELATION_THRESHOLD;
+
+ pr_info("%s: proximity ps_canc = %d, ps_thresh = %d\n",
+ __func__, data->uProxCanc, data->uProxThresh);
+
+ filp_close(cancel_filp, current->files);
+ set_fs(old_fs);
+
+exit:
+ set_proximity_threshold(data);
+
+ 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->uProxThresh = CANCELATION_THRESHOLD;
+ data->uProxCanc = get_proximity_rawdata(data);
+ } else {
+ change_proximity_default_threshold(data);
+ data->uProxCanc = 0;
+ }
+
+ set_proximity_threshold(data);
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ cancel_filp = filp_open(CANCELATION_FILE_PATH,
+ O_CREAT | O_TRUNC | O_WRONLY, 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);
+
+ ssp_dbg("[SSP]: uProxThresh = %u, uProxCanc = %u\n",
+ data->uProxThresh, data->uProxCanc);
+
+ return sprintf(buf, "%u,%u\n", data->uProxCanc, data->uProxThresh);
+}
+
+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_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ssp_data *data = dev_get_drvdata(dev);
+
+ ssp_dbg("[SSP]: uProxThresh = %u\n", data->uProxThresh);
+
+ return sprintf(buf, "%u\n", data->uProxThresh);
+}
+
+static ssize_t proximity_thresh_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ u8 uNewThresh = 0x09;
+ 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.", __func__);
+
+ data->uProxThresh = uNewThresh;
+ set_proximity_threshold(data);
+
+ ssp_dbg("[SSP]: %s - new prox threshold = 0x%x\n",
+ __func__, data->uProxThresh);
+
+ 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 = strict_strtoll(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(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(prox_thresh, S_IRUGO | S_IWUSR | S_IWGRP,
+ proximity_thresh_show, proximity_thresh_store);
+
+static struct device_attribute *prox_attrs[] = {
+ &dev_attr_vendor,
+ &dev_attr_name,
+ &dev_attr_state,
+ &dev_attr_prox_avg,
+ &dev_attr_prox_cal,
+ &dev_attr_prox_thresh,
+ &dev_attr_barcode_emul_en,
+ NULL,
+};
+
+void initialize_prox_factorytest(struct ssp_data *data)
+{
+ struct device *prox_device = NULL;
+
+ sensors_register(prox_device, data, prox_attrs, "proximity_sensor");
+}