ssp_debug.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /*
  2. * Copyright (C) 2012, Samsung Electronics Co. Ltd. All Rights Reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. */
  15. #include "ssp.h"
  16. #define SSP_DEBUG_TIMER_SEC (10 * HZ)
  17. #define LIMIT_RESET_CNT 20
  18. #define LIMIT_SSD_FAIL_CNT 3
  19. #define LIMIT_INSTRUCTION_FAIL_CNT 1
  20. #define LIMIT_IRQ_FAIL_CNT 2
  21. #define LIMIT_TIMEOUT_CNT 5
  22. /*************************************************************************/
  23. /* SSP Debug timer function */
  24. /*************************************************************************/
  25. int print_mcu_debug(char *pchRcvDataFrame, int *pDataIdx,
  26. int iRcvDataFrameLength)
  27. {
  28. int iLength = pchRcvDataFrame[0];
  29. if (iLength >= iRcvDataFrameLength - *pDataIdx - 1 || iLength <= 0) {
  30. ssp_dbg("[SSP]: MSG From MCU - invalid debug length(%d/%d)\n",
  31. iLength, iRcvDataFrameLength);
  32. return iLength ? iLength : ERROR;
  33. }
  34. pchRcvDataFrame[iLength] = 0;
  35. *pDataIdx += iLength + 2;
  36. ssp_dbg("[SSP]: MSG From MCU - %s\n", pchRcvDataFrame + 1);
  37. return 0;
  38. }
  39. void reset_mcu(struct ssp_data *data)
  40. {
  41. func_dbg();
  42. ssp_enable(data, false);
  43. toggle_mcu_reset(data);
  44. msleep(SSP_SW_RESET_TIME);
  45. if (initialize_mcu(data) < 0)
  46. return;
  47. ssp_enable(data, true);
  48. sync_sensor_state(data);
  49. #ifdef CONFIG_SENSORS_SSP_SENSORHUB
  50. ssp_sensorhub_report_notice(data, MSG2SSP_AP_STATUS_RESET);
  51. #endif
  52. }
  53. void sync_sensor_state(struct ssp_data *data)
  54. {
  55. unsigned char uBuf[2] = {0,};
  56. unsigned int uSensorCnt;
  57. int iRet = 0;
  58. proximity_open_calibration(data);
  59. iRet = set_hw_offset(data);
  60. if (iRet < 0) {
  61. pr_err("[SSP]: %s - set_hw_offset failed\n", __func__);
  62. }
  63. udelay(10);
  64. for (uSensorCnt = 0; uSensorCnt < SENSOR_MAX; uSensorCnt++) {
  65. if (atomic_read(&data->aSensorEnable) & (1 << uSensorCnt)) {
  66. uBuf[1] = (u8)get_msdelay(data->adDelayBuf[uSensorCnt]);
  67. uBuf[0] = (u8)get_delay_cmd(uBuf[1]);
  68. send_instruction(data, ADD_SENSOR, uSensorCnt, uBuf, 2);
  69. udelay(10);
  70. }
  71. }
  72. if (data->bProximityRawEnabled == true) {
  73. uBuf[0] = 1;
  74. uBuf[1] = 20;
  75. send_instruction(data, ADD_SENSOR, PROXIMITY_RAW, uBuf, 2);
  76. }
  77. }
  78. static void print_sensordata(struct ssp_data *data, unsigned int uSensor)
  79. {
  80. switch (uSensor) {
  81. case ACCELEROMETER_SENSOR:
  82. case GYROSCOPE_SENSOR:
  83. case GEOMAGNETIC_SENSOR:
  84. ssp_dbg("[SSP] %u : %d, %d, %d (%ums)\n", uSensor,
  85. data->buf[uSensor].x, data->buf[uSensor].y,
  86. data->buf[uSensor].z,
  87. get_msdelay(data->adDelayBuf[uSensor]));
  88. break;
  89. case PRESSURE_SENSOR:
  90. ssp_dbg("[SSP] %u : %d, %d (%ums)\n", uSensor,
  91. data->buf[uSensor].pressure[0],
  92. data->buf[uSensor].pressure[1],
  93. get_msdelay(data->adDelayBuf[uSensor]));
  94. break;
  95. case GESTURE_SENSOR:
  96. ssp_dbg("[SSP] %u : %d %d %d %d (%ums)\n", uSensor,
  97. data->buf[uSensor].data[0], data->buf[uSensor].data[1],
  98. data->buf[uSensor].data[2], data->buf[uSensor].data[3],
  99. get_msdelay(data->adDelayBuf[uSensor]));
  100. break;
  101. case TEMPERATURE_HUMIDITY_SENSOR:
  102. ssp_dbg("[SSP] %u : %d %d %d(%ums)\n", uSensor,
  103. data->buf[uSensor].data[0], data->buf[uSensor].data[1],
  104. data->buf[uSensor].data[2], get_msdelay(data->adDelayBuf[uSensor]));
  105. break;
  106. case LIGHT_SENSOR:
  107. ssp_dbg("[SSP] %u : %u, %u, %u, %u (%ums)\n", uSensor,
  108. data->buf[uSensor].r, data->buf[uSensor].g,
  109. data->buf[uSensor].b, data->buf[uSensor].w,
  110. get_msdelay(data->adDelayBuf[uSensor]));
  111. break;
  112. case PROXIMITY_SENSOR:
  113. ssp_dbg("[SSP] %u : %d %d(%ums)\n", uSensor,
  114. data->buf[uSensor].prox[0], data->buf[uSensor].prox[1],
  115. get_msdelay(data->adDelayBuf[uSensor]));
  116. break;
  117. case SIG_MOTION_SENSOR:
  118. ssp_dbg("[SSP] %u : %u(%ums)\n", uSensor,
  119. data->buf[uSensor].sig_motion,
  120. get_msdelay(data->adDelayBuf[uSensor]));
  121. break;
  122. case STEP_DETECTOR:
  123. ssp_dbg("[SSP] %u : %u(%ums)\n", uSensor,
  124. data->buf[uSensor].step_det,
  125. get_msdelay(data->adDelayBuf[uSensor]));
  126. break;
  127. case STEP_COUNTER:
  128. ssp_dbg("[SSP] %u : %u(%ums)\n", uSensor,
  129. data->buf[uSensor].step_diff,
  130. get_msdelay(data->adDelayBuf[uSensor]));
  131. break;
  132. default:
  133. ssp_dbg("[SSP] Wrong sensorCnt: %u\n", uSensor);
  134. break;
  135. }
  136. }
  137. static void debug_work_func(struct work_struct *work)
  138. {
  139. unsigned int uSensorCnt;
  140. struct ssp_data *data = container_of(work, struct ssp_data, work_debug);
  141. ssp_dbg("[SSP]: %s(%u) - Sensor state: 0x%x, RC: %u, MS: %u\n",
  142. __func__, data->uIrqCnt, data->uSensorState, data->uResetCnt,
  143. data->uMissSensorCnt);
  144. if (data->fw_dl_state >= FW_DL_STATE_DOWNLOADING &&
  145. data->fw_dl_state < FW_DL_STATE_DONE) {
  146. pr_info("[SSP] : %s firmware downloading state = %d\n",
  147. __func__, data->fw_dl_state);
  148. return;
  149. } else if (data->fw_dl_state == FW_DL_STATE_FAIL) {
  150. pr_err("[SSP] : %s firmware download failed = %d\n",
  151. __func__, data->fw_dl_state);
  152. return;
  153. }
  154. for (uSensorCnt = 0; uSensorCnt < SENSOR_MAX; uSensorCnt++)
  155. if (atomic_read(&data->aSensorEnable) & (1 << uSensorCnt))
  156. print_sensordata(data, uSensorCnt);
  157. if ((atomic_read(&data->aSensorEnable) & SSP_BYPASS_SENSORS_EN_ALL)\
  158. && (data->uIrqCnt == 0))
  159. data->uIrqFailCnt++;
  160. else
  161. data->uIrqFailCnt = 0;
  162. if (((data->uSsdFailCnt >= LIMIT_SSD_FAIL_CNT)
  163. || (data->uInstFailCnt >= LIMIT_INSTRUCTION_FAIL_CNT)
  164. || (data->uIrqFailCnt >= LIMIT_IRQ_FAIL_CNT)
  165. || ((data->uTimeOutCnt + data->uBusyCnt) > LIMIT_TIMEOUT_CNT))
  166. && (data->bSspShutdown == false)) {
  167. if (data->uResetCnt < LIMIT_RESET_CNT) {
  168. pr_info("[SSP] : %s - uSsdFailCnt(%u), uInstFailCnt(%u),"\
  169. "uIrqFailCnt(%u), uTimeOutCnt(%u), uBusyCnt(%u)\n",
  170. __func__, data->uSsdFailCnt, data->uInstFailCnt, data->uIrqFailCnt,
  171. data->uTimeOutCnt, data->uBusyCnt);
  172. reset_mcu(data);
  173. data->uResetCnt++;
  174. } else
  175. ssp_enable(data, false);
  176. data->uSsdFailCnt = 0;
  177. data->uInstFailCnt = 0;
  178. data->uTimeOutCnt = 0;
  179. data->uBusyCnt = 0;
  180. data->uIrqFailCnt = 0;
  181. }
  182. data->uIrqCnt = 0;
  183. }
  184. static void debug_timer_func(unsigned long ptr)
  185. {
  186. struct ssp_data *data = (struct ssp_data *)ptr;
  187. queue_work(data->debug_wq, &data->work_debug);
  188. mod_timer(&data->debug_timer,
  189. round_jiffies_up(jiffies + SSP_DEBUG_TIMER_SEC));
  190. }
  191. void enable_debug_timer(struct ssp_data *data)
  192. {
  193. mod_timer(&data->debug_timer,
  194. round_jiffies_up(jiffies + SSP_DEBUG_TIMER_SEC));
  195. }
  196. void disable_debug_timer(struct ssp_data *data)
  197. {
  198. del_timer_sync(&data->debug_timer);
  199. cancel_work_sync(&data->work_debug);
  200. }
  201. int initialize_debug_timer(struct ssp_data *data)
  202. {
  203. setup_timer(&data->debug_timer, debug_timer_func, (unsigned long)data);
  204. data->debug_wq = create_singlethread_workqueue("ssp_debug_wq");
  205. if (!data->debug_wq)
  206. return ERROR;
  207. INIT_WORK(&data->work_debug, debug_work_func);
  208. return SUCCESS;
  209. }