lsm6dso_gyro.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  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 <linux/init.h>
  16. #include <linux/module.h>
  17. #include "adsp.h"
  18. #define VENDOR "STM"
  19. #if IS_ENABLED(CONFIG_LSM6DSV_FACTORY)
  20. #define CHIP_ID "LSM6DSV"
  21. #else
  22. #define CHIP_ID "LSM6DSO"
  23. #endif
  24. #define ST_PASS 1
  25. #define ST_FAIL 0
  26. #define STARTUP_BIT_FAIL 2
  27. #define OIS_ST_BIT_SET 3
  28. #define G_ZRL_DELTA_FAIL 4
  29. #define OIS_RW_FAIL 5
  30. #define SFLP_FAIL 6
  31. #define SELFTEST_REVISED 1
  32. static ssize_t gyro_vendor_show(struct device *dev,
  33. struct device_attribute *attr, char *buf)
  34. {
  35. return snprintf(buf, PAGE_SIZE, "%s\n", VENDOR);
  36. }
  37. static ssize_t gyro_name_show(struct device *dev,
  38. struct device_attribute *attr, char *buf)
  39. {
  40. return snprintf(buf, PAGE_SIZE, "%s\n", CHIP_ID);
  41. }
  42. static ssize_t selftest_revised_show(struct device *dev,
  43. struct device_attribute *attr, char *buf)
  44. {
  45. return snprintf(buf, PAGE_SIZE, "%d\n", SELFTEST_REVISED);
  46. }
  47. static ssize_t gyro_power_off(struct device *dev,
  48. struct device_attribute *attr, char *buf)
  49. {
  50. pr_info("[FACTORY]: %s\n", __func__);
  51. return snprintf(buf, PAGE_SIZE, "%d\n", 1);
  52. }
  53. static ssize_t gyro_power_on(struct device *dev,
  54. struct device_attribute *attr, char *buf)
  55. {
  56. pr_info("[FACTORY]: %s\n", __func__);
  57. return snprintf(buf, PAGE_SIZE, "%d\n", 1);
  58. }
  59. static ssize_t gyro_temp_show(struct device *dev,
  60. struct device_attribute *attr, char *buf)
  61. {
  62. struct adsp_data *data = dev_get_drvdata(dev);
  63. uint8_t cnt = 0;
  64. adsp_unicast(NULL, 0, MSG_GYRO_TEMP, 0, MSG_TYPE_GET_RAW_DATA);
  65. while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << MSG_GYRO_TEMP)
  66. && cnt++ < TIMEOUT_CNT)
  67. msleep(20);
  68. data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_GYRO_TEMP);
  69. if (cnt >= TIMEOUT_CNT) {
  70. pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
  71. return snprintf(buf, PAGE_SIZE, "-99\n");
  72. }
  73. pr_info("[FACTORY] %s: gyro_temp = %d\n", __func__,
  74. data->msg_buf[MSG_GYRO_TEMP][0]);
  75. return snprintf(buf, PAGE_SIZE, "%d\n",
  76. data->msg_buf[MSG_GYRO_TEMP][0]);
  77. }
  78. static ssize_t gyro_selftest_show(struct device *dev,
  79. struct device_attribute *attr, char *buf)
  80. {
  81. struct adsp_data *data = dev_get_drvdata(dev);
  82. uint8_t cnt = 0;
  83. int st_diff_res = ST_FAIL;
  84. int st_zro_res = ST_FAIL;
  85. #if IS_ENABLED(CONFIG_SUPPORT_AK09973) || defined(CONFIG_SUPPORT_AK09973)
  86. int msg_buf = LSM6DSO_SELFTEST_TRUE;
  87. adsp_unicast(&msg_buf, sizeof(msg_buf),
  88. MSG_DIGITAL_HALL_ANGLE, 0, MSG_TYPE_OPTION_DEFINE);
  89. #elif IS_ENABLED(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL) || defined(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL)
  90. int msg_buf = LSM6DSO_SELFTEST_TRUE;
  91. adsp_unicast(&msg_buf, sizeof(msg_buf),
  92. MSG_REF_ANGLE, 0, MSG_TYPE_OPTION_DEFINE);
  93. #endif
  94. pr_info("[FACTORY] %s - start\n", __func__);
  95. adsp_unicast(NULL, 0, MSG_GYRO, 0, MSG_TYPE_ST_SHOW_DATA);
  96. while (!(data->ready_flag[MSG_TYPE_ST_SHOW_DATA] & 1 << MSG_GYRO) &&
  97. cnt++ < TIMEOUT_CNT)
  98. usleep_range(30000, 30100); /* 30 * 200 = 6 sec */
  99. data->ready_flag[MSG_TYPE_ST_SHOW_DATA] &= ~(1 << MSG_GYRO);
  100. if (cnt >= TIMEOUT_CNT) {
  101. pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
  102. #ifdef CONFIG_SEC_FACTORY
  103. panic("sensor force crash : gyro selftest timeout\n");
  104. #endif
  105. #if IS_ENABLED(CONFIG_SUPPORT_AK09973) || defined(CONFIG_SUPPORT_AK09973) ||\
  106. IS_ENABLED(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL) || defined(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL)
  107. schedule_delayed_work(&data->lsm6dso_selftest_stop_work, msecs_to_jiffies(300));
  108. #endif
  109. return snprintf(buf, PAGE_SIZE,
  110. "0,0,0,0,0,0,0,0,0,0,0,0,%d,%d\n",
  111. ST_FAIL, ST_FAIL);
  112. }
  113. if (data->msg_buf[MSG_GYRO][1] != 0) {
  114. pr_info("[FACTORY] %s - failed(%d, %d)\n", __func__,
  115. data->msg_buf[MSG_GYRO][1],
  116. data->msg_buf[MSG_GYRO][5]);
  117. pr_info("[FACTORY]: %s - %d,%d,%d\n", __func__,
  118. data->msg_buf[MSG_GYRO][2],
  119. data->msg_buf[MSG_GYRO][3],
  120. data->msg_buf[MSG_GYRO][4]);
  121. if (data->msg_buf[MSG_GYRO][5] == OIS_ST_BIT_SET)
  122. pr_info("[FACTORY] %s - OIS_ST_BIT fail\n", __func__);
  123. else if (data->msg_buf[MSG_GYRO][5] == G_ZRL_DELTA_FAIL)
  124. pr_info("[FACTORY] %s - ZRL Delta fail\n", __func__);
  125. else if (data->msg_buf[MSG_GYRO][5] == OIS_RW_FAIL)
  126. pr_info("[FACTORY] %s - Gyro OIS read write fail\n", __func__);
  127. #if IS_ENABLED(CONFIG_SUPPORT_AK09973) || defined(CONFIG_SUPPORT_AK09973) ||\
  128. IS_ENABLED(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL) || defined(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL)
  129. schedule_delayed_work(&data->lsm6dso_selftest_stop_work, msecs_to_jiffies(300));
  130. #endif
  131. return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n",
  132. data->msg_buf[MSG_GYRO][2],
  133. data->msg_buf[MSG_GYRO][3],
  134. data->msg_buf[MSG_GYRO][4]);
  135. } else {
  136. st_zro_res = ST_PASS;
  137. }
  138. if (!data->msg_buf[MSG_GYRO][5])
  139. st_diff_res = ST_PASS;
  140. else if (data->msg_buf[MSG_GYRO][5] == STARTUP_BIT_FAIL)
  141. pr_info("[FACTORY] %s - Gyro Start Up Bit fail\n", __func__);
  142. else if (data->msg_buf[MSG_GYRO][5] == OIS_RW_FAIL) {
  143. pr_info("[FACTORY] %s - Gyro OIS read write fail\n", __func__);
  144. st_diff_res = OIS_RW_FAIL;
  145. }
  146. else if (data->msg_buf[MSG_GYRO][5] == SFLP_FAIL) {
  147. pr_info("[FACTORY] %s - SFLP sanity test fail\n", __func__);
  148. st_diff_res = SFLP_FAIL;
  149. }
  150. pr_info("[FACTORY] %s - %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
  151. __func__,
  152. data->msg_buf[MSG_GYRO][2], data->msg_buf[MSG_GYRO][3],
  153. data->msg_buf[MSG_GYRO][4], data->msg_buf[MSG_GYRO][6],
  154. data->msg_buf[MSG_GYRO][7], data->msg_buf[MSG_GYRO][8],
  155. data->msg_buf[MSG_GYRO][9], data->msg_buf[MSG_GYRO][10],
  156. data->msg_buf[MSG_GYRO][11], data->msg_buf[MSG_GYRO][12],
  157. data->msg_buf[MSG_GYRO][13], data->msg_buf[MSG_GYRO][14],
  158. st_diff_res, st_zro_res);
  159. #if IS_ENABLED(CONFIG_SUPPORT_AK09973) || defined(CONFIG_SUPPORT_AK09973) ||\
  160. IS_ENABLED(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL) || defined(CONFIG_SUPPORT_REF_ANGLE_WITHOUT_DIGITAL_HALL)
  161. schedule_delayed_work(&data->lsm6dso_selftest_stop_work, msecs_to_jiffies(300));
  162. #endif
  163. return snprintf(buf, PAGE_SIZE,
  164. "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
  165. data->msg_buf[MSG_GYRO][2], data->msg_buf[MSG_GYRO][3],
  166. data->msg_buf[MSG_GYRO][4], data->msg_buf[MSG_GYRO][6],
  167. data->msg_buf[MSG_GYRO][7], data->msg_buf[MSG_GYRO][8],
  168. data->msg_buf[MSG_GYRO][9], data->msg_buf[MSG_GYRO][10],
  169. data->msg_buf[MSG_GYRO][11], data->msg_buf[MSG_GYRO][12],
  170. data->msg_buf[MSG_GYRO][13], data->msg_buf[MSG_GYRO][14],
  171. st_diff_res, st_zro_res);
  172. }
  173. static ssize_t trimmed_odr_show(struct device *dev,
  174. struct device_attribute *attr, char *buf)
  175. {
  176. struct adsp_data *data = dev_get_drvdata(dev);
  177. uint8_t cnt = 0;
  178. adsp_unicast(NULL, 0, MSG_GYRO, 0, MSG_TYPE_GET_REGISTER);
  179. while (!(data->ready_flag[MSG_TYPE_GET_REGISTER] & 1 << MSG_GYRO)
  180. && cnt++ < TIMEOUT_CNT)
  181. msleep(20);
  182. data->ready_flag[MSG_TYPE_GET_REGISTER] &= ~(1 << MSG_GYRO);
  183. if (cnt >= TIMEOUT_CNT) {
  184. pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
  185. return snprintf(buf, PAGE_SIZE, "0\n");
  186. }
  187. pr_info("[FACTORY] %s: 0x63h = 0x%02x, trimmed_odr = %d Hz\n", __func__,
  188. data->msg_buf[MSG_GYRO][0], data->msg_buf[MSG_GYRO][1]);
  189. return snprintf(buf, PAGE_SIZE, "%d\n",
  190. data->msg_buf[MSG_GYRO][1]);
  191. }
  192. static DEVICE_ATTR(name, 0444, gyro_name_show, NULL);
  193. static DEVICE_ATTR(vendor, 0444, gyro_vendor_show, NULL);
  194. static DEVICE_ATTR(selftest, 0440, gyro_selftest_show, NULL);
  195. static DEVICE_ATTR(power_on, 0444, gyro_power_on, NULL);
  196. static DEVICE_ATTR(power_off, 0444, gyro_power_off, NULL);
  197. static DEVICE_ATTR(temperature, 0440, gyro_temp_show, NULL);
  198. static DEVICE_ATTR(selftest_revised, 0440, selftest_revised_show, NULL);
  199. static DEVICE_ATTR(trimmed_odr, 0440, trimmed_odr_show, NULL);
  200. static struct device_attribute *gyro_attrs[] = {
  201. &dev_attr_name,
  202. &dev_attr_vendor,
  203. &dev_attr_selftest,
  204. &dev_attr_power_on,
  205. &dev_attr_power_off,
  206. &dev_attr_temperature,
  207. &dev_attr_selftest_revised,
  208. &dev_attr_trimmed_odr,
  209. NULL,
  210. };
  211. int __init lsm6dso_gyro_factory_init(void)
  212. {
  213. adsp_factory_register(MSG_GYRO, gyro_attrs);
  214. pr_info("[FACTORY] %s\n", __func__);
  215. return 0;
  216. }
  217. void __exit lsm6dso_gyro_factory_exit(void)
  218. {
  219. adsp_factory_unregister(MSG_GYRO);
  220. pr_info("[FACTORY] %s\n", __func__);
  221. }