diff options
Diffstat (limited to 'drivers/sensorhub/stm/factory')
-rwxr-xr-x | drivers/sensorhub/stm/factory/accel_mpu6500.c | 311 | ||||
-rwxr-xr-x | drivers/sensorhub/stm/factory/gesture_max88920.c | 147 | ||||
-rwxr-xr-x | drivers/sensorhub/stm/factory/gyro_mpu6500.c | 674 | ||||
-rwxr-xr-x | drivers/sensorhub/stm/factory/light_cm3320.c | 77 | ||||
-rwxr-xr-x | drivers/sensorhub/stm/factory/magnetic_yas532.c | 456 | ||||
-rwxr-xr-x | drivers/sensorhub/stm/factory/mcu_atuc128l5har.c | 282 | ||||
-rwxr-xr-x | drivers/sensorhub/stm/factory/mcu_stm32f401.c | 282 | ||||
-rwxr-xr-x | drivers/sensorhub/stm/factory/pressure_bmp182.c | 197 | ||||
-rwxr-xr-x | drivers/sensorhub/stm/factory/prox_max88920.c | 457 | ||||
-rwxr-xr-x | drivers/sensorhub/stm/factory/temphumidity_shtc1.c | 291 |
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); +} |