hif_sdio_chrdev.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. #include "hif_sdio.h"
  2. #include "hif_sdio_chrdev.h"
  3. static int hif_sdio_proc(void *pvData);
  4. static int hif_sdio_open(struct inode *inode, struct file *file);
  5. static int hif_sdio_release(struct inode *inode, struct file *file);
  6. static long hif_sdio_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
  7. static ssize_t hif_sdio_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos);
  8. UINT32 hifSdioMajor = 0;
  9. #define COMBO_IOC_MAGIC 'h'
  10. #define COMBO_IOCTL_GET_CHIP_ID _IOR(COMBO_IOC_MAGIC, 0, int)
  11. #define COMBO_IOCTL_SET_CHIP_ID _IOW(COMBO_IOC_MAGIC, 1, int)
  12. MTK_WCN_HIF_SDIO_CHIP_INFO gChipInfoArray[] = {
  13. /* MT6620 *//* Not an SDIO standard class device */
  14. {{SDIO_DEVICE(0x037A, 0x020A)}, 0x6620}, /* SDIO1:FUNC1:WIFI */
  15. {{SDIO_DEVICE(0x037A, 0x020B)}, 0x6620}, /* SDIO2:FUNC1:BT+FM+GPS */
  16. {{SDIO_DEVICE(0x037A, 0x020C)}, 0x6620}, /* 2-function (SDIO2:FUNC1:BT+FM+GPS, FUNC2:WIFI) */
  17. /* MT6628 *//* SDIO1: Wi-Fi, SDIO2: BGF */
  18. {{SDIO_DEVICE(0x037A, 0x6628)}, 0x6628},
  19. };
  20. const struct file_operations hifDevOps = {
  21. .owner = THIS_MODULE,
  22. .open = hif_sdio_open,
  23. .release = hif_sdio_release,
  24. .unlocked_ioctl = hif_sdio_unlocked_ioctl,
  25. .read = hif_sdio_read,
  26. };
  27. struct class *pHifClass = NULL;
  28. struct device *pHifDev = NULL;
  29. PUINT8 HifClassName = "hifsdiod";
  30. PUINT8 kObjName = "hifsdiod";
  31. struct task_struct *gConIdQueryThread;
  32. wait_queue_head_t gHifsdiodEvent;
  33. /* OSAL_THREAD gConIdQueryThread; */
  34. /* OSAL_EVENT gHifsdiodEvent; */
  35. PUINT8 gConIdQueryName = "consys-id-query";
  36. INT32 gComboChipId = -1;
  37. INT32 hifsdiod_start(VOID)
  38. {
  39. INT32 iRet = -1;
  40. init_waitqueue_head(&gHifsdiodEvent);
  41. #if 0
  42. osal_event_init(&gHifsdiodEvent);
  43. gConIdQueryThread.pThreadData = NULL;
  44. gConIdQueryThread.pThreadFunc = (size_t *) hif_sdio_proc;
  45. osal_memcpy(gConIdQueryThread.threadName, gConIdQueryName, osal_strlen(gConIdQueryName));
  46. iRet = osal_thread_create(&gConIdQueryThread);
  47. if (iRet < 0) {
  48. HIF_SDIO_ERR_FUNC("osal_thread_create fail...\n");
  49. goto ERR_EXIT1;
  50. }
  51. #else
  52. gConIdQueryThread = kthread_create(hif_sdio_proc, NULL, gConIdQueryName);
  53. if (NULL == gConIdQueryThread) {
  54. HIF_SDIO_ERR_FUNC("osal_thread_create fail...\n");
  55. goto ERR_EXIT1;
  56. }
  57. #endif
  58. #if 0
  59. /* Start STPd thread */
  60. iRet = osal_thread_run(&gConIdQueryThread);
  61. if (iRet < 0) {
  62. HIF_SDIO_ERR_FUNC("osal_thread_run FAILS\n");
  63. goto ERR_EXIT1;
  64. }
  65. #else
  66. if (gConIdQueryThread)
  67. wake_up_process(gConIdQueryThread);
  68. else
  69. goto ERR_EXIT1;
  70. #endif
  71. iRet = 0;
  72. HIF_SDIO_INFO_FUNC("succeed\n");
  73. return iRet;
  74. ERR_EXIT1:
  75. HIF_SDIO_ERR_FUNC("failed\n");
  76. return iRet;
  77. }
  78. INT32 hifsdiod_stop(VOID)
  79. {
  80. if (gConIdQueryThread) {
  81. HIF_SDIO_INFO_FUNC("inform hifsdiod exit..\n");
  82. kthread_stop(gConIdQueryThread);
  83. gConIdQueryThread = NULL;
  84. }
  85. return 0;
  86. }
  87. static int hif_sdio_proc(void *pvData)
  88. {
  89. while (!kthread_should_stop()) {
  90. /* HIF_SDIO_INFO_FUNC("enter sleep.\n"); */
  91. osal_sleep_ms(10000);
  92. /* HIF_SDIO_INFO_FUNC("wakeup\n"); */
  93. }
  94. HIF_SDIO_INFO_FUNC("hifsdiod exit.\n");
  95. return 0;
  96. }
  97. static int hif_sdio_open(struct inode *inode, struct file *file)
  98. {
  99. HIF_SDIO_INFO_FUNC(" ++\n");
  100. HIF_SDIO_INFO_FUNC(" --\n");
  101. return 0;
  102. }
  103. static int hif_sdio_release(struct inode *inode, struct file *file)
  104. {
  105. HIF_SDIO_INFO_FUNC(" ++\n");
  106. HIF_SDIO_INFO_FUNC(" --\n");
  107. return 0;
  108. }
  109. static ssize_t hif_sdio_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
  110. {
  111. HIF_SDIO_INFO_FUNC(" ++\n");
  112. HIF_SDIO_INFO_FUNC(" --\n");
  113. return 0;
  114. }
  115. static long hif_sdio_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  116. {
  117. INT32 retval = 0;
  118. HIF_SDIO_DBG_FUNC("cmd (%d)\n", cmd);
  119. switch (cmd) {
  120. case COMBO_IOCTL_GET_CHIP_ID:
  121. gComboChipId = 0x6628;
  122. retval = gComboChipId;
  123. HIF_SDIO_INFO_FUNC("get combo chip id: 0x%x\n", gComboChipId);
  124. break;
  125. case COMBO_IOCTL_SET_CHIP_ID:
  126. gComboChipId = arg;
  127. HIF_SDIO_INFO_FUNC("set combo chip id to 0x%x\n", gComboChipId);
  128. break;
  129. default:
  130. HIF_SDIO_WARN_FUNC("unknown cmd (%d)\n", cmd);
  131. retval = 0;
  132. break;
  133. }
  134. return retval;
  135. }
  136. INT32 hif_sdio_is_chipid_valid(INT32 chipId)
  137. {
  138. INT32 index = -1;
  139. INT32 left = 0;
  140. INT32 middle = 0;
  141. INT32 right = ARRAY_SIZE(gChipInfoArray) - 1;
  142. if ((chipId < gChipInfoArray[left].chipId) || (chipId > gChipInfoArray[right].chipId))
  143. return index;
  144. middle = (left + right) / 2;
  145. while (left <= right) {
  146. if (chipId > gChipInfoArray[middle].chipId) {
  147. left = middle + 1;
  148. } else if (chipId < gChipInfoArray[middle].chipId) {
  149. right = middle - 1;
  150. } else {
  151. index = middle;
  152. break;
  153. }
  154. middle = (left + right) / 2;
  155. }
  156. if (0 > index)
  157. HIF_SDIO_ERR_FUNC("no supported chipid found\n");
  158. else
  159. HIF_SDIO_INFO_FUNC("index:%d, chipId:0x%x\n", index, gChipInfoArray[index].chipId);
  160. return index;
  161. }
  162. INT32 hif_sdio_match_chipid_by_dev_id(const struct sdio_device_id *id)
  163. {
  164. INT32 maxIndex = ARRAY_SIZE(gChipInfoArray);
  165. INT32 index = 0;
  166. struct sdio_device_id *localId = NULL;
  167. INT32 chipId = -1;
  168. for (index = 0; index < maxIndex; index++) {
  169. localId = &(gChipInfoArray[index].deviceId);
  170. if ((localId->vendor == id->vendor) && (localId->device == id->device)) {
  171. chipId = gChipInfoArray[index].chipId;
  172. HIF_SDIO_INFO_FUNC
  173. ("valid chipId found, index(%d), vendor id(0x%x), device id(0x%x), chip id(0x%x)\n",
  174. index, localId->vendor, localId->device, chipId);
  175. gComboChipId = chipId;
  176. break;
  177. }
  178. }
  179. if (0 > chipId) {
  180. HIF_SDIO_ERR_FUNC("No valid chipId found, vendor id(0x%x), device id(0x%x)\n",
  181. id->vendor, id->device);
  182. }
  183. return chipId;
  184. }
  185. INT32 mtk_wcn_hif_sdio_query_chipid(INT32 waitFlag)
  186. {
  187. UINT32 timeSlotMs = 200;
  188. UINT32 maxTimeSlot = 15;
  189. UINT32 counter = 0;
  190. /* gComboChipId = 0x6628; */
  191. if (0 == waitFlag)
  192. return gComboChipId;
  193. if (0 <= hif_sdio_is_chipid_valid(gComboChipId))
  194. return gComboChipId;
  195. wmt_plat_pwr_ctrl(FUNC_ON);
  196. wmt_plat_sdio_ctrl(WMT_SDIO_SLOT_SDIO1, FUNC_ON);
  197. while (counter < maxTimeSlot) {
  198. if (0 <= hif_sdio_is_chipid_valid(gComboChipId))
  199. break;
  200. osal_sleep_ms(timeSlotMs);
  201. counter++;
  202. }
  203. wmt_plat_sdio_ctrl(WMT_SDIO_SLOT_SDIO1, FUNC_OFF);
  204. wmt_plat_pwr_ctrl(FUNC_OFF);
  205. return gComboChipId;
  206. }
  207. EXPORT_SYMBOL(mtk_wcn_hif_sdio_query_chipid);
  208. INT32 mtk_wcn_hif_sdio_tell_chipid(INT32 chipId)
  209. {
  210. gComboChipId = chipId;
  211. HIF_SDIO_INFO_FUNC("set combo chip id to 0x%x\n", gComboChipId);
  212. return gComboChipId;
  213. }
  214. EXPORT_SYMBOL(mtk_wcn_hif_sdio_tell_chipid);
  215. INT32 hif_sdio_create_dev_node(VOID)
  216. {
  217. INT32 iResult = -1;
  218. HIF_SDIO_DBG_FUNC("++");
  219. iResult = register_chrdev(hifSdioMajor, kObjName, &hifDevOps);
  220. if (0 > iResult) {
  221. HIF_SDIO_ERR_FUNC("register_chrdev failed.\n");
  222. iResult = -1;
  223. } else {
  224. hifSdioMajor = hifSdioMajor == 0 ? iResult : hifSdioMajor;
  225. HIF_SDIO_INFO_FUNC("register_chrdev succeed, mtk_jajor = %d\n", hifSdioMajor);
  226. pHifClass = class_create(THIS_MODULE, HifClassName);
  227. if (IS_ERR(pHifClass)) {
  228. HIF_SDIO_ERR_FUNC("class_create error\n");
  229. iResult = -2;
  230. } else {
  231. pHifDev =
  232. device_create(pHifClass, NULL, MKDEV(hifSdioMajor, 0), NULL,
  233. HifClassName, "%d", 0);
  234. if (IS_ERR(pHifDev)) {
  235. HIF_SDIO_ERR_FUNC("device_create error:%ld\n", PTR_ERR(pHifDev));
  236. iResult = -3;
  237. } else {
  238. HIF_SDIO_INFO_FUNC("device_create succeed\n");
  239. iResult = 0;
  240. }
  241. }
  242. }
  243. return iResult;
  244. }
  245. INT32 hif_sdio_remove_dev_node(VOID)
  246. {
  247. if (pHifDev != NULL) {
  248. device_destroy(pHifClass, MKDEV(hifSdioMajor, 0));
  249. pHifDev = NULL;
  250. }
  251. if (pHifClass != NULL) {
  252. class_destroy(pHifClass);
  253. pHifClass = NULL;
  254. }
  255. if (hifSdioMajor != 0) {
  256. unregister_chrdev(hifSdioMajor, kObjName);
  257. hifSdioMajor = 0;
  258. }
  259. return 0;
  260. }