aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sensorhub/stm/ssp_comm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sensorhub/stm/ssp_comm.c')
-rwxr-xr-xdrivers/sensorhub/stm/ssp_comm.c898
1 files changed, 898 insertions, 0 deletions
diff --git a/drivers/sensorhub/stm/ssp_comm.c b/drivers/sensorhub/stm/ssp_comm.c
new file mode 100755
index 00000000000..e01548652cb
--- /dev/null
+++ b/drivers/sensorhub/stm/ssp_comm.c
@@ -0,0 +1,898 @@
+/*
+ * 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 <mach/gpio.h>
+#include "ssp.h"
+
+#define LIMIT_DELAY_CNT 200
+#define RECEIVEBUFFERSIZE 12
+#define DEBUG_SHOW_DATA 0
+
+int waiting_wakeup_mcu(struct ssp_data *data)
+{
+ int iDelaycnt = 0;
+
+ while (!data->check_mcu_busy() && (iDelaycnt++ < LIMIT_DELAY_CNT)
+ && (data->bSspShutdown == false))
+ mdelay(5);
+
+ if (iDelaycnt >= LIMIT_DELAY_CNT) {
+ pr_err("[SSP]: %s - MCU Irq Timeout!!\n", __func__);
+ data->uBusyCnt++;
+ } else {
+ data->uBusyCnt = 0;
+ }
+
+ iDelaycnt = 0;
+ data->wakeup_mcu();
+ while (!data->check_mcu_ready() && (iDelaycnt++ < LIMIT_DELAY_CNT)
+ && (data->bSspShutdown == false))
+ mdelay(5);
+
+ if (iDelaycnt >= LIMIT_DELAY_CNT) {
+ pr_err("[SSP]: %s - MCU Wakeup Timeout!!\n", __func__);
+ data->uTimeOutCnt++;
+ } else {
+ data->uTimeOutCnt = 0;
+ }
+
+ if (data->bSspShutdown == true)
+ return ERROR;
+
+ return SUCCESS;
+}
+
+int waiting_init_mcu(struct ssp_data *data)
+{
+ int iDelaycnt = 0;
+
+ while (!data->check_mcu_busy() && (iDelaycnt++ < LIMIT_DELAY_CNT))
+ mdelay(5);
+
+ if (iDelaycnt >= LIMIT_DELAY_CNT) {
+ pr_err("[SSP]: %s - MCU Irq Timeout!!\n", __func__);
+ data->uBusyCnt++;
+ } else {
+ data->uBusyCnt = 0;
+ }
+
+ iDelaycnt = 0;
+ data->wakeup_mcu();
+ while (!data->check_mcu_ready() && (iDelaycnt++ < LIMIT_DELAY_CNT))
+ mdelay(5);
+
+ if (iDelaycnt >= LIMIT_DELAY_CNT) {
+ pr_err("[SSP]: %s - MCU Wakeup Timeout!!\n", __func__);
+ data->uTimeOutCnt++;
+ } else {
+ data->uTimeOutCnt = 0;
+ }
+
+ return SUCCESS;
+}
+
+int ssp_spi_checkrecvstart(char *rxBuf, int len)
+{
+ unsigned int i;
+ for (i = 0; i < len ; i++) {
+ if (rxBuf[i] == 0x00)
+ continue;
+ break;
+ }
+
+ if (i == len)
+ return -EFAULT;
+ return i;
+}
+
+#if DEBUG_SHOW_DATA
+void show_ssp_data(char *buff, int len, int type)
+{
+ unsigned int i;
+ char showdata[len*2+2];
+ memset(showdata, 0, len*2+2);
+ for (i = 0; i < len; i++)
+ sprintf(showdata, "%s%02x", showdata, buff[i]);
+
+ if (type == 1)
+ pr_info("[SSP]hb received len=%d %s", len, showdata);
+ else if (type == 2)
+ pr_info("[SSP]hb received while send %s", showdata);
+ else
+ pr_info("[SSP]hb sending len=%d %s", len, showdata);
+}
+
+#endif
+
+
+int ssp_read_data(struct ssp_data *data, char *pTxData, u16 uTxLength,
+ char *pRxData, u16 uRxLength, int iRetries)
+{
+ int iRet = 0, iDiffTime = 0, iTimeTemp;
+ int txlen = uTxLength;
+ struct timeval cur_time;
+
+ do_gettimeofday(&cur_time);
+
+ iTimeTemp = (int)cur_time.tv_sec;
+
+#if DEBUG_SHOW_DATA
+ show_ssp_data(pTxData, txlen, 3);
+#endif
+
+ mutex_lock(&data->comm_mutex);
+
+ do {
+ char synctxbuf[RECEIVEBUFFERSIZE];
+ char syncrxbuf[RECEIVEBUFFERSIZE];
+ char *bulktxbuf;
+ char *bulkrxbuf;
+
+ int startpos;
+
+ if (pTxData[0] != MSG2SSP_SRM) {
+ /* 0xCA : MASS DATA will be received */
+ memset(synctxbuf, 0, RECEIVEBUFFERSIZE);
+
+ /* prevent re-sending CMD when retry */
+ if (txlen > 0)
+ memcpy(synctxbuf, pTxData, uTxLength);
+
+ /* uTxLength should small than RECEIVEBUFFERSIZE */
+ iRet = ssp_spi_sync(data->spi, synctxbuf,
+ RECEIVEBUFFERSIZE, syncrxbuf);
+
+#if DEBUG_SHOW_DATA
+ show_ssp_data(syncrxbuf, RECEIVEBUFFERSIZE, 2);
+#endif
+
+ startpos = ssp_spi_checkrecvstart(syncrxbuf + txlen,
+ RECEIVEBUFFERSIZE - txlen) + txlen;
+#if DEBUG_SHOW_DATA
+ pr_info("[SSP]hb pTxData[0]=0x%x startpos "
+ "%d uTxLength %d,uRxLen %d",
+ pTxData[0], startpos, uTxLength, uRxLength);
+#endif
+ if (startpos >= txlen &&
+ (RECEIVEBUFFERSIZE - startpos - uRxLength >= 0))
+ memcpy(pRxData, syncrxbuf + startpos,
+ uRxLength);
+ else /* timeout if receive within RECEIVEBUFFERSIZE */
+ iRet = -ETIMEDOUT;
+
+ } else {
+ bulktxbuf = (char *)kzalloc(
+ uRxLength + RECEIVEBUFFERSIZE, GFP_KERNEL);
+ bulkrxbuf = (char *)kzalloc(
+ uRxLength + RECEIVEBUFFERSIZE, GFP_KERNEL);
+
+ /* prevent re-sending command when retry */
+ if (txlen > 0)
+ memcpy(bulktxbuf, pTxData, txlen);
+ iRet = ssp_spi_sync(data->spi, bulktxbuf,
+ uRxLength+RECEIVEBUFFERSIZE, bulkrxbuf);
+
+#if DEBUG_SHOW_DATA
+ show_ssp_data(bulkrxbuf,
+ uRxLength + RECEIVEBUFFERSIZE, 2);
+#endif
+
+ startpos = ssp_spi_checkrecvstart(bulkrxbuf + txlen,
+ uRxLength + RECEIVEBUFFERSIZE - txlen)
+ + txlen;
+#if DEBUG_SHOW_DATA
+ pr_info("[SSP]hb WOW pTxData[0]=0x%x startpos %d "
+ "uTxLength %d,uRxLen %d TxLen %d", pTxData[0],
+ startpos, uTxLength, uRxLength, txlen);
+#endif
+
+ if (startpos >= txlen &&
+ (uRxLength + RECEIVEBUFFERSIZE -
+ startpos - uRxLength >= 0))
+ memcpy(pRxData, bulkrxbuf + startpos,
+ uRxLength);
+ else /* timeout if receive within RECEIVEBUFFERSIZE */
+ iRet = -1;
+
+ kfree(bulktxbuf);
+ kfree(bulkrxbuf);
+ }
+
+ if (iRet < 0) {
+ do_gettimeofday(&cur_time);
+ iDiffTime = (int)cur_time.tv_sec - iTimeTemp;
+ iTimeTemp = (int)cur_time.tv_sec;
+ if (iDiffTime >= 4) {
+ pr_err("[SSP]: %s - spi time out %d!\n",
+ __func__, iDiffTime);
+ break;
+ }
+ pr_err("[SSP]: %s - spi error %d! retry...\n",
+ __func__, iRet);
+ mdelay(1);
+ } else {
+#if DEBUG_SHOW_DATA
+ show_ssp_data(pRxData, uRxLength, 1);
+#endif
+ mutex_unlock(&data->comm_mutex);
+
+ return SUCCESS;
+ }
+ txlen = 0;
+ } while (iRetries--);
+ mutex_unlock(&data->comm_mutex);
+
+ return ERROR;
+}
+
+int ssp_sleep_mode(struct ssp_data *data)
+{
+ char chRxBuf = 0;
+ char chTxBuf = MSG2SSP_AP_STATUS_SLEEP;
+ int iRet = 0, iRetries = DEFAULT_RETRIES;
+
+ if (waiting_wakeup_mcu(data) < 0)
+ return ERROR;
+
+ /* send to AP_STATUS_SLEEP */
+ iRet = ssp_read_data(data, &chTxBuf, 1, &chRxBuf, 1, DEFAULT_RETRIES);
+ if (iRet != SUCCESS) {
+ pr_err("[SSP]: %s - MSG2SSP_AP_STATUS_SLEEP CMD fail %d\n",
+ __func__, iRet);
+ return ERROR;
+ } else if (chRxBuf != MSG_ACK) {
+ while (iRetries--) {
+ mdelay(10);
+ pr_err("[SSP]: %s - MSG2SSP_AP_STATUS_SLEEP CMD "\
+ "retry...\n", __func__);
+ iRet = ssp_read_data(data, &chTxBuf, 1,
+ &chRxBuf, 1, DEFAULT_RETRIES);
+ if ((iRet == SUCCESS) && (chRxBuf == MSG_ACK))
+ break;
+ }
+
+ if (iRetries < 0) {
+ data->uInstFailCnt++;
+ return FAIL;
+ }
+ }
+
+ data->uInstFailCnt = 0;
+ ssp_dbg("[SSP]: %s - MSG2SSP_AP_STATUS_SLEEP CMD\n", __func__);
+
+ return SUCCESS;
+}
+
+int ssp_resume_mode(struct ssp_data *data)
+{
+ char chRxBuf = 0;
+ char chTxBuf = MSG2SSP_AP_STATUS_WAKEUP;
+ int iRet = 0, iRetries = DEFAULT_RETRIES;
+
+ if (waiting_wakeup_mcu(data) < 0)
+ return ERROR;
+
+ /* send to MSG2SSP_AP_STATUS_WAKEUP */
+ iRet = ssp_read_data(data, &chTxBuf, 1, &chRxBuf, 1, DEFAULT_RETRIES);
+ if (iRet != SUCCESS) {
+ pr_err("[SSP]: %s - MSG2SSP_AP_STATUS_WAKEUP CMD fail %d\n",
+ __func__, iRet);
+ return ERROR;
+ } else if (chRxBuf != MSG_ACK) {
+ while (iRetries--) {
+ mdelay(10);
+ pr_err("[SSP]: %s - MSG2SSP_AP_STATUS_WAKEUP CMD "\
+ "retry...\n", __func__);
+ iRet = ssp_read_data(data, &chTxBuf, 1, &chRxBuf, 1,
+ DEFAULT_RETRIES);
+ if ((iRet == SUCCESS) && (chRxBuf == MSG_ACK))
+ break;
+ }
+
+ if (iRetries < 0) {
+ data->uInstFailCnt++;
+ return FAIL;
+ }
+ }
+
+ data->uInstFailCnt = 0;
+ ssp_dbg("[SSP]: %s - MSG2SSP_AP_STATUS_WAKEUP CMD\n", __func__);
+
+ return SUCCESS;
+}
+
+int ssp_ap_suspend(struct ssp_data *data)
+{
+ char chRxBuf = 0;
+ char chTxBuf = MSG2SSP_AP_STATUS_SUSPEND;
+ int iRet = 0, iRetries = DEFAULT_RETRIES;
+
+ if (waiting_wakeup_mcu(data) < 0)
+ return ERROR;
+
+ /* send to AP_STATUS_SLEEP */
+ iRet = ssp_read_data(data, &chTxBuf, 1, &chRxBuf, 1, DEFAULT_RETRIES);
+ if (iRet != SUCCESS) {
+ pr_err("[SSP]: %s - MSG2SSP_AP_STATUS_SLEEP CMD fail %d\n",
+ __func__, iRet);
+ return ERROR;
+ } else if (chRxBuf != MSG_ACK) {
+ while (iRetries--) {
+ mdelay(10);
+ pr_err("[SSP]: %s - MSG2SSP_AP_STATUS_SLEEP CMD "\
+ "retry...\n", __func__);
+ iRet = ssp_read_data(data, &chTxBuf, 1,
+ &chRxBuf, 1, DEFAULT_RETRIES);
+ if ((iRet == SUCCESS) && (chRxBuf == MSG_ACK))
+ break;
+ }
+
+ if (iRetries < 0) {
+ data->uInstFailCnt++;
+ return FAIL;
+ }
+ }
+
+ data->uInstFailCnt = 0;
+ ssp_dbg("[SSP]: %s - MSG2SSP_AP_STATUS_SLEEP CMD\n", __func__);
+
+ return SUCCESS;
+}
+
+int ssp_ap_resume(struct ssp_data *data)
+{
+ char chRxBuf = 0;
+ char chTxBuf = MSG2SSP_AP_STATUS_RESUME;
+ int iRet = 0, iRetries = DEFAULT_RETRIES;
+
+ if (waiting_wakeup_mcu(data) < 0)
+ return ERROR;
+
+ /* send to MSG2SSP_AP_STATUS_WAKEUP */
+ iRet = ssp_read_data(data, &chTxBuf, 1, &chRxBuf, 1, DEFAULT_RETRIES);
+ if (iRet != SUCCESS) {
+ pr_err("[SSP]: %s - MSG2SSP_AP_STATUS_WAKEUP CMD fail %d\n",
+ __func__, iRet);
+ return ERROR;
+ } else if (chRxBuf != MSG_ACK) {
+ while (iRetries--) {
+ mdelay(10);
+ pr_err("[SSP]: %s - MSG2SSP_AP_STATUS_WAKEUP CMD "\
+ "retry...\n", __func__);
+ iRet = ssp_read_data(data, &chTxBuf, 1, &chRxBuf, 1,
+ DEFAULT_RETRIES);
+ if ((iRet == SUCCESS) && (chRxBuf == MSG_ACK))
+ break;
+ }
+
+ if (iRetries < 0) {
+ data->uInstFailCnt++;
+ return FAIL;
+ }
+ }
+
+ data->uInstFailCnt = 0;
+ ssp_dbg("[SSP]: %s - MSG2SSP_AP_STATUS_WAKEUP CMD\n", __func__);
+
+ return SUCCESS;
+}
+
+int ssp_send_cmd(struct ssp_data *data, char command)
+{
+ char chRxBuf = 0;
+ int iRet = 0, iRetries = DEFAULT_RETRIES;
+
+ if (waiting_wakeup_mcu(data) < 0)
+ return ERROR;
+
+ iRet = ssp_read_data(data, &command, 1, &chRxBuf, 1, DEFAULT_RETRIES);
+ if (iRet != SUCCESS) {
+ pr_err("[SSP]: %s - command 0x%x failed %d\n",
+ __func__, command, iRet);
+ return ERROR;
+ } else if (chRxBuf != MSG_ACK) {
+ while (iRetries--) {
+ mdelay(10);
+ pr_err("[SSP]: %s - command 0x%x retry...\n",
+ __func__, command);
+ iRet = ssp_read_data(data, &command, 1, &chRxBuf, 1,
+ DEFAULT_RETRIES);
+ if ((iRet == SUCCESS) && (chRxBuf == MSG_ACK))
+ break;
+ }
+
+ if (iRetries < 0) {
+ data->uInstFailCnt++;
+ return FAIL;
+ }
+ }
+
+ data->uInstFailCnt = 0;
+ ssp_dbg("[SSP]: %s - command 0x%x\n", __func__, command);
+
+ return SUCCESS;
+}
+
+int send_instruction(struct ssp_data *data, u8 uInst,
+ u8 uSensorType, u8 *uSendBuf, u8 uLength)
+{
+ char chTxbuf[uLength + 4];
+ char chRxbuf = 0;
+ int iRet = 0, iRetries = DEFAULT_RETRIES;
+
+ if (data->fw_dl_state == FW_DL_STATE_DOWNLOADING) {
+ pr_err("[SSP] %s - Skip Inst! DL state = %d\n",
+ __func__, data->fw_dl_state);
+ return SUCCESS;
+ } else if ((!(data->uSensorState & (1 << uSensorType)))
+ && (uInst <= CHANGE_DELAY)) {
+ pr_err("[SSP]: %s - Bypass Inst Skip! - %u\n",
+ __func__, uSensorType);
+ return FAIL;
+ }
+
+ if (waiting_wakeup_mcu(data) < 0)
+ return ERROR;
+
+ chTxbuf[0] = MSG2SSP_SSM;
+ chTxbuf[1] = (char)(uLength + 4);
+
+ switch (uInst) {
+ case REMOVE_SENSOR:
+ chTxbuf[2] = MSG2SSP_INST_BYPASS_SENSOR_REMOVE;
+ break;
+ case ADD_SENSOR:
+ chTxbuf[2] = MSG2SSP_INST_BYPASS_SENSOR_ADD;
+ break;
+ case CHANGE_DELAY:
+ chTxbuf[2] = MSG2SSP_INST_CHANGE_DELAY;
+ break;
+ case GO_SLEEP:
+ chTxbuf[2] = MSG2SSP_AP_STATUS_SLEEP;
+ break;
+ case FACTORY_MODE:
+ chTxbuf[2] = MSG2SSP_INST_SENSOR_SELFTEST;
+ break;
+ case REMOVE_LIBRARY:
+ chTxbuf[2] = MSG2SSP_INST_LIBRARY_REMOVE;
+ break;
+ case ADD_LIBRARY:
+ chTxbuf[2] = MSG2SSP_INST_LIBRARY_ADD;
+ break;
+ case MSG2SSP_INST_LIB_NOTI:
+ if (uSendBuf[0] == MSG2SSP_AP_STATUS_WAKEUP) {
+ iRet = ssp_resume_mode(data);
+ enable_debug_timer(data);
+ } else if (uSendBuf[0] == MSG2SSP_AP_STATUS_SLEEP) {
+ disable_debug_timer(data);
+ iRet = ssp_sleep_mode(data);
+ } else {
+ pr_err("[SSP]: %s -Wrong POWER_NOTI 0x%x\n", __func__,
+ uSendBuf[0]);
+ return ERROR;
+ }
+ return iRet;
+ default:
+ chTxbuf[2] = uInst;
+ break;
+ }
+
+ chTxbuf[3] = uSensorType;
+ memcpy(&chTxbuf[4], uSendBuf, uLength);
+
+ iRet = ssp_read_data(data, &(chTxbuf[0]), uLength + 4, &chRxbuf, 1,
+ DEFAULT_RETRIES);
+ if (iRet != SUCCESS) {
+ pr_err("[SSP]: %s - Instruction CMD Fail %d\n", __func__, iRet);
+ return ERROR;
+ } else if (chRxbuf != MSG_ACK) {
+ while (iRetries--) {
+ mdelay(10);
+ pr_err("[SSP]: %s - Instruction CMD retry...\n",
+ __func__);
+ if (waiting_wakeup_mcu(data) < 0)
+ return ERROR;
+ iRet = ssp_read_data(data, &(chTxbuf[0]),
+ uLength + 4, &chRxbuf, 1, DEFAULT_RETRIES);
+ if ((iRet == SUCCESS) && (chRxbuf == MSG_ACK))
+ break;
+ }
+
+ if (iRetries < 0) {
+ data->uInstFailCnt++;
+ return FAIL;
+ }
+ }
+
+ data->uInstFailCnt = 0;
+ ssp_dbg("[SSP]: %s - Inst = 0x%x, Sensor Type = 0x%x, data = %u\n",
+ __func__, chTxbuf[2], chTxbuf[3], chTxbuf[4]);
+ return SUCCESS;
+}
+
+int get_chipid(struct ssp_data *data)
+{
+ int iRet;
+ char sendbuf[2];
+ char recvbuf;
+ sendbuf[0] = MSG2SSP_AP_WHOAMI;
+ sendbuf[1] = '\0';
+
+ if (waiting_init_mcu(data) < 0)
+ return ERROR;
+
+ /* read chip id */
+#if 1
+ iRet = ssp_read_data(data, sendbuf, 2, &recvbuf, 1, DEFAULT_RETRIES);
+
+ if (iRet == SUCCESS)
+ return recvbuf;
+ else
+ pr_err("[SSP]: %s - ssp_read_data fail %d\n", __func__, iRet);
+
+ return ERROR;
+#else
+ mutex_lock(&data->comm_mutex);
+
+ iRet = ssp_spi_sync(data->spi, sendbuf, 1, NULL);
+ pr_err("[SSP]hb get_chipid ssp_spi_sync return for send %d", iRet);
+
+ iRet = ssp_spi_sync(data->spi, NULL, 1, recvbuf);
+ pr_err("[SSP]hb get_chipid ssp_spi_sync return for recv %d", iRet);
+ iRet = recvbuf[0];
+ pr_err("[SSP]hb get_chipid ssp_spi_sync recved %d", iRet);
+
+ mutex_unlock(&data->comm_mutex);
+#endif
+}
+
+int set_sensor_position(struct ssp_data *data)
+{
+ char chTxBuf[5] = { 0, };
+ char chRxData = 0;
+ int iRet = 0;
+
+ if (waiting_init_mcu(data) < 0)
+ return ERROR;
+
+ chTxBuf[0] = MSG2SSP_AP_SENSOR_FORMATION;
+
+ /* Please refer to ssp_get_positions on the file
+ * board-universal_5410-sensor.c */
+ chTxBuf[1] = data->accel_position;
+ chTxBuf[2] = data->accel_position;
+ chTxBuf[3] = data->mag_position;
+ chTxBuf[4] = 0;
+
+ pr_info("[SSP] Sensor Posision A : %u, G : %u, M: %u, P: %u\n",
+ chTxBuf[1], chTxBuf[2], chTxBuf[3], chTxBuf[4]);
+
+ iRet = ssp_read_data(data, chTxBuf, 5, &chRxData, 1, DEFAULT_RETRIES);
+ if ((chRxData != MSG_ACK) || (iRet != SUCCESS)) {
+ pr_err("[SSP]: %s - spi fail %d\n", __func__, iRet);
+ iRet = ERROR;
+ }
+
+ return iRet;
+}
+
+void set_proximity_threshold(struct ssp_data *data,
+ unsigned char uData1, unsigned char uData2)
+{
+ char chTxBuf[3] = { 0, };
+ char chRxBuf = 0;
+ int iRet = 0, iRetries = DEFAULT_RETRIES;
+
+ 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;
+ } else if (!(data->uSensorState & (1 << PROXIMITY_SENSOR))) {
+ pr_info("[SSP] : %s, skip uSensorState = 0x%x\n", __func__,
+ data->uSensorState);
+ return;
+ }
+
+ chTxBuf[0] = MSG2SSP_AP_SENSOR_PROXTHRESHOLD;
+ chTxBuf[1] = uData1;
+ chTxBuf[2] = uData2;
+
+ iRet = ssp_read_data(data, chTxBuf, 3, &chRxBuf, 1, DEFAULT_RETRIES);
+ if (iRet != SUCCESS) {
+ pr_err("[SSP]: %s - SENSOR_PROXTHRESHOLD CMD fail %d\n",
+ __func__, iRet);
+ return;
+ } else if (chRxBuf != MSG_ACK) {
+ while (iRetries--) {
+ mdelay(10);
+ pr_err("[SSP]: %s - MSG2SSP_AP_SENSOR_PROXTHRESHOLD "\
+ "CMD retry...\n", __func__);
+ iRet = ssp_read_data(data, chTxBuf, 3, &chRxBuf, 1,
+ DEFAULT_RETRIES);
+ if ((iRet == SUCCESS) && (chRxBuf == MSG_ACK))
+ break;
+ }
+
+ if (iRetries < 0) {
+ data->uInstFailCnt++;
+ return;
+ }
+ }
+
+ data->uInstFailCnt = 0;
+ pr_info("[SSP]: Proximity Threshold - %u, %u\n", uData1, uData2);
+}
+
+void set_proximity_barcode_enable(struct ssp_data *data, bool bEnable)
+{
+ char chTxBuf[2] = { 0, };
+ char chRxBuf = 0;
+ int iRet = 0, iRetries = DEFAULT_RETRIES;
+
+ if (waiting_wakeup_mcu(data) < 0)
+ return;
+
+ chTxBuf[0] = MSG2SSP_AP_SENSOR_BARCODE_EMUL;
+ chTxBuf[1] = bEnable;
+
+ data->bBarcodeEnabled = bEnable;
+
+ iRet = ssp_read_data(data, chTxBuf, 2, &chRxBuf, 1, DEFAULT_RETRIES);
+ if (iRet != SUCCESS) {
+ pr_err("[SSP]: %s - SENSOR_BARCODE_EMUL CMD fail %d\n",
+ __func__, iRet);
+ return;
+ } else if (chRxBuf != MSG_ACK) {
+ while (iRetries--) {
+ mdelay(10);
+ pr_err("[SSP]: %s - MSG2SSP_AP_SENSOR_BARCODE_EMUL "\
+ "CMD retry...\n", __func__);
+ iRet = ssp_read_data(data, chTxBuf, 2, &chRxBuf, 1,
+ DEFAULT_RETRIES);
+ if ((iRet == SUCCESS) && (chRxBuf == MSG_ACK))
+ break;
+ }
+
+ if (iRetries < 0) {
+ data->uInstFailCnt++;
+ return;
+ }
+ }
+
+ data->uInstFailCnt = 0;
+ pr_info("[SSP] Proximity Barcode En : %u\n", bEnable);
+}
+
+void set_gesture_current(struct ssp_data *data, unsigned char uData1)
+{
+ char chTxBuf[2] = { 0, };
+ char chRxBuf = 0;
+ int iRet = 0, iRetries = DEFAULT_RETRIES;
+
+ 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;
+ }
+
+ chTxBuf[0] = MSG2SSP_AP_SENSOR_GESTURE_CURRENT;
+ chTxBuf[1] = uData1;
+
+ iRet = ssp_read_data(data, chTxBuf, 2, &chRxBuf, 1, DEFAULT_RETRIES);
+ if (iRet != SUCCESS) {
+ pr_err("[SSP]: %s - SENSOR_GESTURE_CURRENT CMD fail %d\n",
+ __func__, iRet);
+ return;
+ } else if (chRxBuf != MSG_ACK) {
+ while (iRetries--) {
+ mdelay(10);
+ pr_err("[SSP]: %s - MSG2SSP_AP_SENSOR_GESTURE_CURRENT "\
+ "CMD retry...\n", __func__);
+ iRet = ssp_read_data(data, chTxBuf, 2, &chRxBuf, 1,
+ DEFAULT_RETRIES);
+ if ((iRet == SUCCESS) && (chRxBuf == MSG_ACK))
+ break;
+ }
+
+ if (iRetries < 0) {
+ data->uInstFailCnt++;
+ return;
+ }
+ }
+
+ data->uInstFailCnt = 0;
+ pr_info("[SSP]: Gesture Current Setting - %u\n", uData1);
+}
+
+unsigned int get_sensor_scanning_info(struct ssp_data *data)
+{
+ char chTxBuf = MSG2SSP_AP_SENSOR_SCANNING;
+ char chRxData[2] = {0,};
+ int iRet = 0;
+
+ if (waiting_init_mcu(data) < 0)
+ return ERROR;
+
+ iRet = ssp_read_data(data, &chTxBuf, 1, chRxData, 2, DEFAULT_RETRIES);
+ if (iRet != SUCCESS) {
+ pr_err("[SSP]: %s - spi failed %d\n", __func__, iRet);
+ return 0;
+ }
+ return ((unsigned int)chRxData[0] << 8) | chRxData[1];
+}
+
+unsigned int get_firmware_rev(struct ssp_data *data)
+{
+ char chTxData = MSG2SSP_AP_FIRMWARE_REV;
+ char chRxBuf[3] = { 0, };
+ unsigned int uRev = 99999;
+ int iRet;
+
+ if (waiting_wakeup_mcu(data) < 0)
+ return ERROR;
+
+ iRet = ssp_read_data(data, &chTxData, 1, chRxBuf, 3, DEFAULT_RETRIES);
+ if (iRet != SUCCESS)
+ pr_err("[SSP]: %s - spi fail %d\n", __func__, iRet);
+ else
+ uRev = ((unsigned int)chRxBuf[0] << 16)
+ | ((unsigned int)chRxBuf[1] << 8) | chRxBuf[2];
+ return uRev;
+}
+
+int get_fuserom_data(struct ssp_data *data)
+{
+ char chTxBuf[2] = { 0, };
+ char chRxBuf[2] = { 0, };
+ int iRet = 0;
+ unsigned int uLength = 0;
+
+ if (waiting_init_mcu(data) < 0)
+ return ERROR;
+
+ chTxBuf[0] = MSG2SSP_AP_STT;
+ chTxBuf[1] = MSG2SSP_AP_FUSEROM;
+
+ /* chRxBuf is Two Byte because msg is large */
+ iRet = ssp_read_data(data, chTxBuf, 2, chRxBuf, 2, DEFAULT_RETRIES);
+ uLength = ((unsigned int)chRxBuf[0] << 8) + (unsigned int)chRxBuf[1];
+
+ if (iRet != SUCCESS) {
+ pr_err("[SSP]: %s - MSG2SSP_AP_STT - spi fail %d\n",
+ __func__, iRet);
+ goto err_read_fuserom;
+ } else if (uLength == 0) {
+ pr_err("[SSP]: %s - No ready data. length = %u\n",
+ __func__, uLength);
+ goto err_read_fuserom;
+ } else {
+ if (data->iLibraryLength != 0)
+ kfree(data->pchLibraryBuf);
+
+ data->iLibraryLength = (int)uLength;
+ data->pchLibraryBuf =
+ kzalloc((data->iLibraryLength * sizeof(char)), GFP_KERNEL);
+
+ chTxBuf[0] = MSG2SSP_SRM;
+ iRet = ssp_read_data(data, chTxBuf, 1, data->pchLibraryBuf,
+ (u16)data->iLibraryLength, DEFAULT_RETRIES);
+ if (iRet != SUCCESS) {
+ pr_err("[SSP]: %s - Fail to receive SSP data %d\n",
+ __func__, iRet);
+ kfree(data->pchLibraryBuf);
+ data->iLibraryLength = 0;
+ goto err_read_fuserom;
+ }
+ }
+
+ data->uFuseRomData[0] = data->pchLibraryBuf[0];
+ data->uFuseRomData[1] = data->pchLibraryBuf[1];
+ data->uFuseRomData[2] = data->pchLibraryBuf[2];
+
+ pr_info("[SSP] FUSE ROM Data %d , %d, %d\n", data->uFuseRomData[0],
+ data->uFuseRomData[1], data->uFuseRomData[2]);
+
+ data->iLibraryLength = 0;
+ kfree(data->pchLibraryBuf);
+ return SUCCESS;
+
+err_read_fuserom:
+ data->uFuseRomData[0] = 0;
+ data->uFuseRomData[1] = 0;
+ data->uFuseRomData[2] = 0;
+
+ return FAIL;
+}
+
+static int ssp_receive_msg(struct ssp_data *data, u8 uLength)
+{
+ char chTxBuf = 0;
+ char *pchRcvDataFrame = NULL; /* SSP-AP Massage data buffer */
+ int iRet = 0;
+
+ if (uLength > 0) {
+ pchRcvDataFrame = kzalloc((uLength * sizeof(char)), GFP_KERNEL);
+ if (pchRcvDataFrame == NULL) {
+ pr_err("[SSP]: %s - fail to allocate memory for data\n",
+ __func__);
+ iRet = -ENOMEM;
+ return iRet;
+ }
+ chTxBuf = MSG2SSP_SRM;
+ iRet = ssp_read_data(data, &chTxBuf, 1, pchRcvDataFrame,
+ (u16)uLength, 0);
+ if (iRet != SUCCESS) {
+ pr_err("[SSP]: %s - Fail to receive data %d\n",
+ __func__, iRet);
+ kfree(pchRcvDataFrame);
+ return ERROR;
+ }
+ } else {
+ pr_err("[SSP]: %s - No ready data. length = %d\n",
+ __func__, uLength);
+ return FAIL;
+ }
+
+ parse_dataframe(data, pchRcvDataFrame, uLength);
+
+ kfree(pchRcvDataFrame);
+ return uLength;
+}
+
+int select_irq_msg(struct ssp_data *data)
+{
+ u8 chLength = 0;
+ char chTxBuf = 0;
+ char chRxBuf[2] = { 0, };
+ int iRet = 0;
+
+ chTxBuf = MSG2SSP_SSD;
+ iRet = ssp_read_data(data, &chTxBuf, 1, chRxBuf, 2, 4);
+
+ if (iRet != SUCCESS) {
+ pr_err("[SSP]: %s - MSG2SSP_SSD error %d\n", __func__, iRet);
+ return ERROR;
+ } else {
+ if (chRxBuf[0] == MSG2SSP_RTS) {
+ chLength = (u8)chRxBuf[1];
+ ssp_receive_msg(data, chLength);
+ data->uSsdFailCnt = 0;
+ }
+#ifdef CONFIG_SENSORS_SSP_SENSORHUB
+ else if (chRxBuf[0] == MSG2SSP_STT) {
+ pr_info("%s: MSG2SSP_STT irq", __func__);
+ iRet = ssp_sensorhub_handle_large_data(data,
+ (u8)chRxBuf[1]);
+ if (iRet < 0) {
+ pr_err("%s: ssp sensorhub large data err(%d)",
+ __func__, iRet);
+ }
+ data->uSsdFailCnt = 0;
+ }
+#endif
+ else if (chRxBuf[0] == MSG2SSP_NO_DATA) {
+ pr_info("%s: MSG2SSP_NODATA irq [0]: 0x%x, [1]: 0x%x\n",
+ __func__, chRxBuf[0], chRxBuf[1]);
+ } else {
+ pr_err("[SSP]: %s - MSG2SSP_SSD Data fail "\
+ "[0]: 0x%x, [1]: 0x%x\n", __func__,
+ chRxBuf[0], chRxBuf[1]);
+ if ((chRxBuf[0] == 0) && (chRxBuf[1] == 0))
+ data->uSsdFailCnt++;
+ }
+ }
+ return SUCCESS;
+}