ak09918_mag.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  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 "AKM"
  19. #define CHIP_ID "AK09918"
  20. #define MAG_ST_TRY_CNT 3
  21. #define ABS(x) (((x)>0)?(x):-(x))
  22. #define AKM_ST_FAIL (-1)
  23. static ssize_t mag_vendor_show(struct device *dev,
  24. struct device_attribute *attr, char *buf)
  25. {
  26. return snprintf(buf, PAGE_SIZE, "%s\n", VENDOR);
  27. }
  28. static ssize_t mag_name_show(struct device *dev,
  29. struct device_attribute *attr, char *buf)
  30. {
  31. return snprintf(buf, PAGE_SIZE, "%s\n", CHIP_ID);
  32. }
  33. static ssize_t mag_check_cntl(struct device *dev,
  34. struct device_attribute *attr, char *buf)
  35. {
  36. return snprintf(buf, PAGE_SIZE, "OK\n");
  37. }
  38. static ssize_t mag_check_registers(struct device *dev,
  39. struct device_attribute *attr, char *buf)
  40. {
  41. return snprintf(buf, PAGE_SIZE,
  42. "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
  43. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  44. }
  45. static ssize_t mag_get_asa(struct device *dev,
  46. struct device_attribute *attr, char *buf)
  47. {
  48. /* Do not have Fuserom */
  49. return snprintf(buf, PAGE_SIZE, "%u,%u,%u\n", 128, 128, 128);
  50. }
  51. static ssize_t mag_get_status(struct device *dev,
  52. struct device_attribute *attr, char *buf)
  53. {
  54. /* Do not have Fuserom */
  55. return snprintf(buf, PAGE_SIZE, "%s\n", "OK");
  56. }
  57. static ssize_t mag_raw_data_show(struct device *dev,
  58. struct device_attribute *attr, char *buf)
  59. {
  60. struct adsp_data *data = dev_get_drvdata(dev);
  61. uint8_t cnt = 0;
  62. adsp_unicast(NULL, 0, MSG_MAG, 0, MSG_TYPE_GET_RAW_DATA);
  63. while (!(data->ready_flag[MSG_TYPE_GET_RAW_DATA] & 1 << MSG_MAG) &&
  64. cnt++ < TIMEOUT_CNT)
  65. usleep_range(500, 550);
  66. data->ready_flag[MSG_TYPE_GET_RAW_DATA] &= ~(1 << MSG_MAG);
  67. if (cnt >= TIMEOUT_CNT) {
  68. pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
  69. return snprintf(buf, PAGE_SIZE, "0,0,0\n");
  70. }
  71. return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n",
  72. data->msg_buf[MSG_MAG][0],
  73. data->msg_buf[MSG_MAG][1],
  74. data->msg_buf[MSG_MAG][2]);
  75. }
  76. static ssize_t mag_raw_data_store(struct device *dev,
  77. struct device_attribute *attr, const char *buf, size_t size)
  78. {
  79. adsp_unicast(NULL, 0, MSG_MAG_CAL, 0, MSG_TYPE_FACTORY_ENABLE);
  80. msleep(20);
  81. adsp_unicast(NULL, 0, MSG_MAG_CAL, 0, MSG_TYPE_SET_CAL_DATA);
  82. msleep(20);
  83. adsp_unicast(NULL, 0, MSG_MAG_CAL, 0, MSG_TYPE_FACTORY_DISABLE);
  84. return size;
  85. }
  86. static ssize_t mag_selftest_show(struct device *dev,
  87. struct device_attribute *attr, char *buf)
  88. {
  89. struct adsp_data *data = dev_get_drvdata(dev);
  90. uint8_t cnt = 0;
  91. int retry = 0, i;
  92. int abs_adc_sum = 0, abs_adc_x = 0, abs_adc_y = 0, abs_adc_z = 0;
  93. int st_status = 0;
  94. RETRY_MAG_SELFTEST:
  95. pr_info("[FACTORY] %s - start\n", __func__);
  96. adsp_unicast(NULL, 0, MSG_MAG, 0, MSG_TYPE_ST_SHOW_DATA);
  97. while (!(data->ready_flag[MSG_TYPE_ST_SHOW_DATA] & 1 << MSG_MAG) &&
  98. cnt++ < TIMEOUT_CNT)
  99. msleep(26);
  100. data->ready_flag[MSG_TYPE_ST_SHOW_DATA] &= ~(1 << MSG_MAG);
  101. if (cnt >= TIMEOUT_CNT) {
  102. pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
  103. data->msg_buf[MSG_MAG][0] = -1;
  104. #ifdef CONFIG_SEC_FACTORY
  105. panic("force crash : sensor selftest timeout\n");
  106. #endif
  107. }
  108. if (!(data->msg_buf[MSG_MAG][0] == 0)) {
  109. if (retry < MAG_ST_TRY_CNT) {
  110. retry++;
  111. for (i = 0; i < 10; i++)
  112. data->msg_buf[MSG_MAG][i] = 0;
  113. msleep(100);
  114. cnt = 0;
  115. pr_info("[FACTORY] %s - retry %d\n", __func__, retry);
  116. goto RETRY_MAG_SELFTEST;
  117. }
  118. adsp_unicast(NULL, 0, MSG_MAG_CAL, 0, MSG_TYPE_FACTORY_ENABLE);
  119. msleep(20);
  120. adsp_unicast(NULL, 0, MSG_MAG_CAL, 0, MSG_TYPE_SET_CAL_DATA);
  121. msleep(20);
  122. adsp_unicast(NULL, 0, MSG_MAG_CAL, 0, MSG_TYPE_FACTORY_DISABLE);
  123. return snprintf(buf, PAGE_SIZE, "-1,0,0,0,0,0,0,0,0,0\n");
  124. }
  125. if (data->msg_buf[MSG_MAG][1] != 0) {
  126. pr_info("[FACTORY] %s - msg_buf[1] 0x%x\n", __func__, data->msg_buf[MSG_MAG][1]);
  127. st_status = AKM_ST_FAIL;
  128. }
  129. pr_info("[FACTORY] status=%d, st_status=%d, st_xyz=%d,%d,%d, dac=%d, adc=%d, adc_xyz=%d,%d,%d\n",
  130. data->msg_buf[MSG_MAG][0], st_status,
  131. data->msg_buf[MSG_MAG][2], data->msg_buf[MSG_MAG][3],
  132. data->msg_buf[MSG_MAG][4], data->msg_buf[MSG_MAG][5],
  133. data->msg_buf[MSG_MAG][6], data->msg_buf[MSG_MAG][7],
  134. data->msg_buf[MSG_MAG][8], data->msg_buf[MSG_MAG][9]);
  135. abs_adc_x = ABS(data->msg_buf[MSG_MAG][7]);
  136. abs_adc_y = ABS(data->msg_buf[MSG_MAG][8]);
  137. abs_adc_z = ABS(data->msg_buf[MSG_MAG][9]);
  138. abs_adc_sum = abs_adc_x + abs_adc_y + abs_adc_z;
  139. if (abs_adc_sum >= 26666) {
  140. pr_info("[FACTORY] abs_adc_sum is higher then 40Gauss\n");
  141. st_status = AKM_ST_FAIL;
  142. }
  143. adsp_unicast(NULL, 0, MSG_MAG_CAL, 0, MSG_TYPE_FACTORY_ENABLE);
  144. msleep(20);
  145. adsp_unicast(NULL, 0, MSG_MAG_CAL, 0, MSG_TYPE_SET_CAL_DATA);
  146. msleep(20);
  147. adsp_unicast(NULL, 0, MSG_MAG_CAL, 0, MSG_TYPE_FACTORY_DISABLE);
  148. return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
  149. data->msg_buf[MSG_MAG][0], st_status,
  150. data->msg_buf[MSG_MAG][2], data->msg_buf[MSG_MAG][3],
  151. data->msg_buf[MSG_MAG][4], data->msg_buf[MSG_MAG][5],
  152. data->msg_buf[MSG_MAG][6], data->msg_buf[MSG_MAG][7],
  153. data->msg_buf[MSG_MAG][8], data->msg_buf[MSG_MAG][9]);
  154. }
  155. static ssize_t mag_dhr_sensor_info_show(struct device *dev,
  156. struct device_attribute *attr, char *buf)
  157. {
  158. struct adsp_data *data = dev_get_drvdata(dev);
  159. uint8_t cnt = 0;
  160. adsp_unicast(NULL, 0, MSG_MAG, 0, MSG_TYPE_GET_DHR_INFO);
  161. while (!(data->ready_flag[MSG_TYPE_GET_DHR_INFO] & 1 << MSG_MAG) &&
  162. cnt++ < TIMEOUT_CNT)
  163. usleep_range(500, 550);
  164. data->ready_flag[MSG_TYPE_GET_DHR_INFO] &= ~(1 << MSG_MAG);
  165. if (cnt >= TIMEOUT_CNT) {
  166. pr_err("[FACTORY] %s: Timeout!!!\n", __func__);
  167. } else {
  168. pr_info("[FACTORY] %s - [00h-03h] %02x,%02x,%02x,%02x [10h-16h,18h] %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x [30h-32h] %02x,%02x,%02x\n",
  169. __func__,
  170. data->msg_buf[MSG_MAG][0], data->msg_buf[MSG_MAG][1],
  171. data->msg_buf[MSG_MAG][2], data->msg_buf[MSG_MAG][3],
  172. data->msg_buf[MSG_MAG][4], data->msg_buf[MSG_MAG][5],
  173. data->msg_buf[MSG_MAG][6], data->msg_buf[MSG_MAG][7],
  174. data->msg_buf[MSG_MAG][8], data->msg_buf[MSG_MAG][9],
  175. data->msg_buf[MSG_MAG][10], data->msg_buf[MSG_MAG][11],
  176. data->msg_buf[MSG_MAG][12], data->msg_buf[MSG_MAG][13],
  177. data->msg_buf[MSG_MAG][14]);
  178. }
  179. return snprintf(buf, PAGE_SIZE, "%s\n", "Done");
  180. }
  181. static DEVICE_ATTR(name, 0444, mag_name_show, NULL);
  182. static DEVICE_ATTR(vendor, 0444, mag_vendor_show, NULL);
  183. static DEVICE_ATTR(raw_data, 0664, mag_raw_data_show, mag_raw_data_store);
  184. static DEVICE_ATTR(dac, 0444, mag_check_cntl, NULL);
  185. static DEVICE_ATTR(chk_registers, 0444, mag_check_registers, NULL);
  186. static DEVICE_ATTR(selftest, 0440, mag_selftest_show, NULL);
  187. static DEVICE_ATTR(asa, 0444, mag_get_asa, NULL);
  188. static DEVICE_ATTR(status, 0444, mag_get_status, NULL);
  189. #ifdef CONFIG_SEC_FACTORY
  190. static DEVICE_ATTR(dhr_sensor_info, 0444, mag_dhr_sensor_info_show, NULL);
  191. #else
  192. static DEVICE_ATTR(dhr_sensor_info, 0440, mag_dhr_sensor_info_show, NULL);
  193. #endif
  194. static struct device_attribute *mag_attrs[] = {
  195. &dev_attr_name,
  196. &dev_attr_vendor,
  197. &dev_attr_raw_data,
  198. &dev_attr_dac,
  199. &dev_attr_chk_registers,
  200. &dev_attr_selftest,
  201. &dev_attr_asa,
  202. &dev_attr_status,
  203. &dev_attr_dhr_sensor_info,
  204. NULL,
  205. };
  206. int ak09918_factory_init(void)
  207. {
  208. adsp_factory_register(MSG_MAG, mag_attrs);
  209. pr_info("[FACTORY] %s\n", __func__);
  210. return 0;
  211. }
  212. void ak09918_factory_exit(void)
  213. {
  214. adsp_factory_unregister(MSG_MAG);
  215. pr_info("[FACTORY] %s\n", __func__);
  216. }