hqsysfs.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. /*
  2. * Copyright (C) 2015 MediaTek Inc.
  3. * Copyright (C) 2021 XiaoMi, Inc.
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  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. #include <linux/hqsysfs.h>
  15. #include "hqsys_misc.h"
  16. #include "hqsys_pcba.h"
  17. #define HQ_SYS_FS_VER "2016-03-11 V0.2"
  18. static HW_INFO(HWID_VER, ver);
  19. static HW_INFO(HWID_SUMMARY, hw_summary);
  20. static HW_INFO(HWID_DDR, ram);
  21. static HW_INFO(HWID_EMMC, emmc);
  22. static HW_INFO(HWID_LCM, lcm);
  23. //static HW_INFO(HWID_BIAS_IC,lcm_bias_ic);
  24. static HW_INFO(HWID_CTP, ctp);
  25. static HW_INFO(HWID_SUB_CAM, sub_cam); //sub
  26. static HW_INFO(HWID_SUB_CAM_2, main0_cam); //main0
  27. static HW_INFO(HWID_MAIN_CAM, main1_cam); //main1
  28. static HW_INFO(HWID_MAIN_CAM_2, main2_cam); //main2
  29. static HW_INFO(HWID_MAIN_CAM_3, main3_cam); //main3
  30. static HW_INFO(HWID_MAIN_LENS, main_cam_len);
  31. static HW_INFO(HWID_FLASHLIGHT, flashlight);
  32. static HW_INFO(HWID_GSENSOR, gsensor);
  33. static HW_INFO(HWID_ALSPS, alsps);
  34. static HW_INFO(HWID_MSENSOR, msensor);
  35. static HW_INFO(HWID_GYRO, gyro);
  36. static HW_INFO(HWID_IRDA, irda);
  37. static HW_INFO(HWID_FUEL_GAUGE_IC, fuel_gauge_ic);
  38. static HW_INFO(HWID_NFC, nfc);
  39. static HW_INFO(HWID_FP, fingerprint);
  40. //static HW_INFO(HWID_TEE,tee);
  41. static HW_INFO(HWID_PCBA, pcba_config);
  42. #if defined(TARGET_PRODUCT_LANCELOT) || defined(TARGET_PRODUCT_SHIVA)
  43. struct pcba_info pcba[] = {
  44. {PCBA_J19_P0_1_CN, "PCBA_J19_P0-1_CN"},
  45. {PCBA_J19_P0_1_INDIA, "PCBA_J19_P0-1_INDIA"},
  46. {PCBA_J19_P0_1_GLOBAL, "PCBA_J19_P0-1_GLOBAL"},
  47. {PCBA_J19_P1_CN, "PCBA_J19_P1_CN"},
  48. {PCBA_J19_P1_INDIA, "PCBA_J19_P1_INDIA"},
  49. {PCBA_J19_P1_GLOBAL, "PCBA_J19_P1_GLOBAL"},
  50. {PCBA_J19_P2_CN, "PCBA_J19_P2_CN"},
  51. {PCBA_J19_P2_INDIA, "PCBA_J19_P2_INDIA"},
  52. {PCBA_J19_P2_GLOBAL, "PCBA_J19_P2_GLOBAL"},
  53. {PCBA_J19_MP_CN, "PCBA_J19_MP_CN"},
  54. {PCBA_J19_MP_CN_SP01T, "PCBA_J19_MP_CN_SP01T"},
  55. {PCBA_J19_MP_INDIA, "PCBA_J19_MP_INDIA"},
  56. {PCBA_J19_MP_GLOBAL, "PCBA_J19_MP_GLOBAL"},
  57. {PCBA_J19A_P0_1_GLOBAL, "PCBA_J19A_P0-1_GLOBAL"},
  58. {PCBA_J19A_P1_GLOBAL, "PCBA_J19A_P1_GLOBAL"},
  59. {PCBA_J19A_P2_GLOBAL, "PCBA_J19A_P2_GLOBAL"},
  60. {PCBA_J19A_MP_GLOBAL, "PCBA_J19A_MP_GLOBAL"},
  61. {PCBA_J19P_P2_INDIA, "PCBA_J19P_P2_INDIA"},
  62. {PCBA_J19P_MP_INDIA, "PCBA_J19P_MP_INDIA"},
  63. {PCBA_J19P_POCO_MP_INDIA, "PCBA_J19P_POCO_MP_INDIA"},
  64. };
  65. #else
  66. struct pcba_info pcba[] = {
  67. {PCBA_UNKNOW, "PCBA_UNKNOW"},
  68. {PCBA_J15S_P0_CN, "PCBA_J15S_P0_CN"},
  69. {PCBA_J15S_P0_INDIA, "PCBA_J15S_P0_INDIA"},
  70. {PCBA_J15S_P0_GLOBAL, "PCBA_J15S_P0_GLOBAL"},
  71. {PCBA_J15S_P1_CN, "PCBA_J15S_P1_CN"},
  72. {PCBA_J15S_P1_INDIA, "PCBA_J15S_P1_INDIA"},
  73. {PCBA_J15S_P1_1_CN, "PCBA_J15S_P1-1_CN"},
  74. {PCBA_J15S_P1_1_INDIA, "PCBA_J15S_P1-1_INDIA"},
  75. {PCBA_J15N_P1_1_GLOBAL_NFC, "PCBA_J15N_P1-1_GLOBAL_NFC"},
  76. {PCBA_J15S_P2_CN, "PCBA_J15S_P2_CN"},
  77. {PCBA_J15S_P2_INDIA, "PCBA_J15S_P2_INDIA"},
  78. {PCBA_J15S_P2_GLOBAL, "PCBA_J15S_P2_GLOBAL"},
  79. {PCBA_J15N_P2_GLOBAL_NFC, "PCBA_J15N_P2_GLOBAL_NFC"},
  80. {PCBA_J15S_P2_1_GLOBAL, "PCBA_J15S_P2-1_GLOBAL"},
  81. {PCBA_J15N_P2_1_GLOBAL_NFC, "PCBA_J15N_P2-1_GLOBAL_NFC"},
  82. {PCBA_J15S_MP_CN, "PCBA_J15S_MP_CN"},
  83. {PCBA_J15S_MP_INDIA, "PCBA_J15S_MP_INDIA"},
  84. {PCBA_J15S_MP_GLOBAL, "PCBA_J15S_MP_GLOBAL"},
  85. {PCBA_J15N_MP_GLOBAL_NFC, "PCBA_J15N_MP_GLOBAL_NFC"},
  86. {PCBA_J15S_CN_NEW_PA, "PCBA_J15S_MP_CN_NEW_PA"},
  87. };
  88. #endif
  89. static struct attribute *huaqin_attrs[] = {
  90. &hw_info_ver.attr,
  91. &hw_info_hw_summary.attr,
  92. &hw_info_ram.attr,
  93. &hw_info_emmc.attr,
  94. &hw_info_lcm.attr,
  95. // &hw_info_lcm_bias_ic.attr,
  96. &hw_info_ctp.attr,
  97. &hw_info_sub_cam.attr,
  98. &hw_info_main0_cam.attr,
  99. &hw_info_main1_cam.attr,
  100. &hw_info_main2_cam.attr,
  101. &hw_info_main3_cam.attr,
  102. &hw_info_main_cam_len.attr,
  103. &hw_info_flashlight.attr,
  104. &hw_info_gsensor.attr,
  105. &hw_info_alsps.attr,
  106. &hw_info_msensor.attr,
  107. &hw_info_gyro.attr,
  108. &hw_info_irda.attr,
  109. &hw_info_fuel_gauge_ic.attr,
  110. &hw_info_nfc.attr,
  111. &hw_info_fingerprint.attr,
  112. &hw_info_pcba_config.attr,
  113. // &hw_info_tee.attr,
  114. NULL
  115. };
  116. static ssize_t huaqin_show(struct kobject *kobj, struct attribute *a, char *buf)
  117. {
  118. ssize_t count = 0;
  119. int i = 0;
  120. struct hw_info *hw = container_of(a, struct hw_info, attr);
  121. if (NULL == hw) {
  122. return sprintf(buf, "Data error\n");
  123. }
  124. if (HWID_VER == hw->hw_id) {
  125. count = sprintf(buf, "%s\n", HQ_SYS_FS_VER);
  126. } else if (HWID_SUMMARY == hw->hw_id) {
  127. //iterate all device and output the detail
  128. int iterator = 0;
  129. struct hw_info *curent_hw = NULL;
  130. struct attribute *attr = huaqin_attrs[iterator];
  131. while (attr) {
  132. curent_hw = container_of(attr, struct hw_info, attr);
  133. iterator += 1;
  134. attr = huaqin_attrs[iterator];
  135. if (curent_hw->hw_exist && (NULL != curent_hw->hw_device_name)) {
  136. count += sprintf(buf+count, "%s: %s\n", curent_hw->attr.name, curent_hw->hw_device_name);
  137. }
  138. }
  139. } else if (HWID_PCBA == hw->hw_id) {
  140. if (get_huaqin_pcba_config() >= PCBA_UNKNOW && get_huaqin_pcba_config() < PCBA_END) {
  141. huaqin_pcba_config = get_huaqin_pcba_config();
  142. } else {
  143. huaqin_pcba_config = PCBA_UNKNOW;
  144. }
  145. for (i = 0; i < sizeof(pcba)/sizeof(struct pcba_info); i++) {
  146. if (huaqin_pcba_config == pcba[i].pcba_config) {
  147. count = sprintf(buf, "%s\n", pcba[i].pcba_name);
  148. return count;
  149. }
  150. }
  151. count = sprintf(buf, "%s\n", "PCBA_UNKONW");
  152. } else{
  153. if (0 == hw->hw_exist) {
  154. count = sprintf(buf, "Not support\n");
  155. } else if (NULL == hw->hw_device_name) {
  156. count = sprintf(buf, "Installed with no device Name\n");
  157. } else {
  158. count = sprintf(buf, "%s\n", hw->hw_device_name);
  159. }
  160. }
  161. return count;
  162. }
  163. static ssize_t huaqin_store(struct kobject *kobj, struct attribute *a, const char *buf, size_t count)
  164. {
  165. return count;
  166. }
  167. /* huaqin object */
  168. static struct kobject huaqin_kobj;
  169. static const struct sysfs_ops huaqin_sysfs_ops = {
  170. .show = huaqin_show,
  171. .store = huaqin_store,
  172. };
  173. /* huaqin type */
  174. static struct kobj_type huaqin_ktype = {
  175. .sysfs_ops = &huaqin_sysfs_ops,
  176. .default_attrs = huaqin_attrs
  177. };
  178. /* huaqin device class */
  179. static struct class *huaqin_class;
  180. static struct device *huaqin_hw_device;
  181. int register_kboj_under_hqsysfs(struct kobject *kobj, struct kobj_type *ktype, const char *fmt, ...)
  182. {
  183. return kobject_init_and_add(kobj, ktype, &(huaqin_hw_device->kobj), fmt);
  184. }
  185. static int __init create_sysfs(void)
  186. {
  187. int ret;
  188. /* create class (device model) */
  189. huaqin_class = class_create(THIS_MODULE, HUAQIN_CLASS_NAME);
  190. if (IS_ERR(huaqin_class)) {
  191. pr_err("%s fail to create class\n", __func__);
  192. return -1;
  193. }
  194. huaqin_hw_device = device_create(huaqin_class, NULL, MKDEV(0, 0), NULL, HUAIN_INTERFACE_NAME);
  195. if (IS_ERR(huaqin_hw_device)) {
  196. pr_warn("fail to create device\n");
  197. return -1;
  198. }
  199. /* add kobject */
  200. ret = kobject_init_and_add(&huaqin_kobj, &huaqin_ktype, &(huaqin_hw_device->kobj), HUAQIN_HWID_NAME);
  201. if (ret < 0) {
  202. pr_err("%s fail to add kobject\n", __func__);
  203. return ret;
  204. }
  205. return 0;
  206. }
  207. int hq_deregister_hw_info(enum hardware_id id, char *device_name)
  208. {
  209. int ret = 0;
  210. int find_hw_id = 0;
  211. int iterator = 0;
  212. struct hw_info *hw = NULL;
  213. struct attribute *attr = huaqin_attrs[iterator];
  214. if (NULL == device_name) {
  215. pr_err("[%s]: device_name does not allow empty\n", __func__);
  216. ret = -2;
  217. goto err;
  218. }
  219. while (attr) {
  220. hw = container_of(attr, struct hw_info, attr);
  221. iterator += 1;
  222. attr = huaqin_attrs[iterator];
  223. if (NULL == hw) {
  224. continue;
  225. }
  226. if (id == hw->hw_id) {
  227. find_hw_id = 1;
  228. if (0 == hw->hw_exist) {
  229. pr_err("[%s]: device has not registed hw->id:0x%x . Cant be deregistered\n"
  230. , __func__
  231. , hw->hw_id);
  232. ret = -4;
  233. goto err;
  234. } else if (NULL == hw->hw_device_name) {
  235. pr_err("[%s]:hw_id is 0x%x Device name cant be NULL\n"
  236. , __func__
  237. , hw->hw_id);
  238. ret = -5;
  239. goto err;
  240. } else {
  241. if (0 == strncmp(hw->hw_device_name, device_name, strlen(hw->hw_device_name))) {
  242. hw->hw_device_name = NULL;
  243. hw->hw_exist = 0;
  244. } else{
  245. pr_err("[%s]: hw_id is 0x%x Registered device name %s, want to deregister: %s\n"
  246. , __func__
  247. , hw->hw_id
  248. , hw->hw_device_name
  249. , device_name);
  250. ret = -6;
  251. goto err;
  252. }
  253. }
  254. goto err;
  255. } else
  256. continue;
  257. }
  258. if (0 == find_hw_id) {
  259. pr_err("[%s]: Cant find correct hardware_id: 0x%x\n", __func__, id);
  260. ret = -3;
  261. }
  262. err:
  263. return ret;
  264. }
  265. int hq_regiser_hw_info(enum hardware_id id, char *device_name)
  266. {
  267. int ret = 0;
  268. int find_hw_id = 0;
  269. int iterator = 0;
  270. struct hw_info *hw = NULL;
  271. struct attribute *attr = huaqin_attrs[iterator];
  272. if (NULL == device_name) {
  273. pr_err("[%s]: device_name does not allow empty\n", __func__);
  274. ret = -2;
  275. goto err;
  276. }
  277. while (attr) {
  278. hw = container_of(attr, struct hw_info, attr);
  279. iterator += 1;
  280. attr = huaqin_attrs[iterator];
  281. if (NULL == hw) {
  282. continue;
  283. }
  284. if (id == hw->hw_id) {
  285. find_hw_id = 1;
  286. if (hw->hw_exist) {
  287. pr_err("[%s]: device has already registed hw->id:0x%x hw_device_name:%s\n"
  288. , __func__
  289. , hw->hw_id
  290. , hw->hw_device_name);
  291. ret = -4;
  292. goto err;
  293. }
  294. switch (hw->hw_id) {
  295. /*
  296. if(map_cam_drv_to_vendor(device_name))
  297. hw->hw_device_name = map_cam_drv_to_vendor(device_name);
  298. else
  299. hw->hw_device_name = "Can't find Camera Vendor";
  300. break;
  301. */
  302. default:
  303. hw->hw_device_name = device_name;
  304. break;
  305. }
  306. hw->hw_exist = 1;
  307. goto err;
  308. } else
  309. continue;
  310. }
  311. if (0 == find_hw_id) {
  312. pr_err("[%s]: Cant find correct hardware_id: 0x%x\n", __func__, id);
  313. ret = -3;
  314. }
  315. err:
  316. return ret;
  317. }
  318. #include <linux/proc_fs.h>
  319. #include <linux/of_gpio.h>
  320. #include <linux/gpio.h>
  321. #define PROC_BOOT_REASON_FILE "boot_status"
  322. #define SDC_DETECT_STATUS "sdc_det_gpio_status"
  323. #define SDC_DETECT_GPIO 343
  324. static struct proc_dir_entry *boot_reason_proc;
  325. static struct proc_dir_entry *sdc_detect_status;
  326. static unsigned int boot_into_factory;
  327. static int boot_reason_proc_show(struct seq_file *file, void *data)
  328. {
  329. char temp[40] = {0};
  330. sprintf(temp, "%d\n", boot_into_factory);
  331. seq_printf(file, "%s\n", temp);
  332. return 0;
  333. }
  334. static int boot_reason_proc_open (struct inode *inode, struct file *file)
  335. {
  336. return single_open(file, boot_reason_proc_show, inode->i_private);
  337. }
  338. static const struct file_operations boot_reason_proc_fops = {
  339. .open = boot_reason_proc_open,
  340. .read = seq_read,
  341. };
  342. static int __init get_boot_rease(char *str)
  343. {
  344. if (strcmp("boot_with_factory", str) == 0) {
  345. boot_into_factory = 1;
  346. }
  347. return 0;
  348. }
  349. __setup("androidboot.boot_reason=", get_boot_rease);
  350. static int sdc_detect_proc_show(struct seq_file *file, void *data)
  351. {
  352. int gpio_value = -1;
  353. gpio_value = gpio_get_value(SDC_DETECT_GPIO);
  354. seq_printf(file, "%d\n", gpio_value ? 1 : 0);
  355. return 0;
  356. }
  357. static int sdc_detect_proc_open (struct inode *inode, struct file *file)
  358. {
  359. return single_open(file, sdc_detect_proc_show, inode->i_private);
  360. }
  361. static const struct file_operations sdc_detect_proc_fops = {
  362. .open = sdc_detect_proc_open,
  363. .read = seq_read,
  364. };
  365. static int sdc_detect_init(void)
  366. {
  367. int ret = -1;
  368. sdc_detect_status = proc_create(SDC_DETECT_STATUS, 0644, NULL, &sdc_detect_proc_fops);
  369. if (sdc_detect_status == NULL) {
  370. pr_err("[%s]: create_proc_entry sdc_detect_status failed\n", __func__);
  371. return -1;
  372. }
  373. return 0;
  374. }
  375. static int __init hq_harware_init(void)
  376. {
  377. /* create sysfs entry at /sys/class/huaqin/interface/hw_info */
  378. create_sysfs();
  379. boot_reason_proc = proc_create(PROC_BOOT_REASON_FILE, 0644, NULL, &boot_reason_proc_fops);
  380. if (boot_reason_proc == NULL) {
  381. pr_err("[%s]: create_proc_entry boot_reason_proc failed\n", __func__);
  382. }
  383. if (sdc_detect_init() < 0)
  384. pr_err("[%s]: create_proc_entry sdc_detect_proc failed\n", __func__);
  385. return 0;
  386. }
  387. core_initcall(hq_harware_init);
  388. MODULE_AUTHOR("KaKa Ni <nigang@huaqin.com>");
  389. MODULE_DESCRIPTION("Huaqin Hardware Info Driver");
  390. MODULE_LICENSE("GPL");