sdio_detect.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /*
  2. * Copyright (C) 2011-2014 MediaTek Inc.
  3. *
  4. * This program is free software: you can redistribute it and/or modify it under the terms of the
  5. * GNU General Public License version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  8. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. * See the GNU General Public License for more details.
  10. *
  11. * You should have received a copy of the GNU General Public License along with this program.
  12. * If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. #ifdef DFT_TAG
  15. #undef DFT_TAG
  16. #endif
  17. #define DFT_TAG "[SDIO-DETECT]"
  18. #include "wmt_detect.h"
  19. #if MTK_HIF_SDIO_AUTOK_ENABLED
  20. #include <mt_boot.h>
  21. #endif
  22. unsigned int gComboChipId = -1;
  23. struct sdio_func *g_func = NULL;
  24. MTK_WCN_HIF_SDIO_CHIP_INFO gChipInfoArray[] = {
  25. /* MT6620 *//* Not an SDIO standard class device */
  26. {{SDIO_DEVICE(0x037A, 0x020A)}, 0x6620}, /* SDIO1:FUNC1:WIFI */
  27. {{SDIO_DEVICE(0x037A, 0x020B)}, 0x6620}, /* SDIO2:FUNC1:BT+FM+GPS */
  28. {{SDIO_DEVICE(0x037A, 0x020C)}, 0x6620}, /* 2-function (SDIO2:FUNC1:BT+FM+GPS, FUNC2:WIFI) */
  29. /* MT6628 *//* SDIO1: Wi-Fi, SDIO2: BGF */
  30. {{SDIO_DEVICE(0x037A, 0x6628)}, 0x6628},
  31. /* MT6630 *//* SDIO1: Wi-Fi, SDIO2: BGF */
  32. {{SDIO_DEVICE(0x037A, 0x6630)}, 0x6630},
  33. };
  34. /* Supported SDIO device table */
  35. static const struct sdio_device_id mtk_sdio_id_tbl[] = {
  36. /* MT6618 *//* Not an SDIO standard class device */
  37. {SDIO_DEVICE(0x037A, 0x018A)}, /* SDIO1:WIFI */
  38. {SDIO_DEVICE(0x037A, 0x018B)}, /* SDIO2:FUNC1:BT+FM */
  39. {SDIO_DEVICE(0x037A, 0x018C)}, /* 2-function (SDIO2:FUNC1:BT+FM, FUNC2:WIFI) */
  40. /* MT6619 *//* Not an SDIO standard class device */
  41. {SDIO_DEVICE(0x037A, 0x6619)}, /* SDIO2:FUNC1:BT+FM+GPS */
  42. /* MT6620 *//* Not an SDIO standard class device */
  43. {SDIO_DEVICE(0x037A, 0x020A)}, /* SDIO1:FUNC1:WIFI */
  44. {SDIO_DEVICE(0x037A, 0x020B)}, /* SDIO2:FUNC1:BT+FM+GPS */
  45. {SDIO_DEVICE(0x037A, 0x020C)}, /* 2-function (SDIO2:FUNC1:BT+FM+GPS, FUNC2:WIFI) */
  46. /* MT5921 *//* Not an SDIO standard class device */
  47. {SDIO_DEVICE(0x037A, 0x5921)},
  48. /* MT6628 *//* SDIO1: Wi-Fi, SDIO2: BGF */
  49. {SDIO_DEVICE(0x037A, 0x6628)},
  50. /* MT6630 *//* SDIO1: Wi-Fi, SDIO2: BGF */
  51. {SDIO_DEVICE(0x037A, 0x6630)},
  52. { /* end: all zeroes */ },
  53. };
  54. static int sdio_detect_probe(struct sdio_func *func, const struct sdio_device_id *id);
  55. static void sdio_detect_remove(struct sdio_func *func);
  56. static struct sdio_driver mtk_sdio_client_drv = {
  57. .name = "mtk_sdio_client", /* MTK SDIO Client Driver */
  58. .id_table = mtk_sdio_id_tbl, /* all supported struct sdio_device_id table */
  59. .probe = sdio_detect_probe,
  60. .remove = sdio_detect_remove,
  61. };
  62. static int hif_sdio_match_chipid_by_dev_id(const struct sdio_device_id *id);
  63. int hif_sdio_is_chipid_valid(int chipId)
  64. {
  65. int index = -1;
  66. int left = 0;
  67. int middle = 0;
  68. int right = sizeof(gChipInfoArray) / sizeof(gChipInfoArray[0]) - 1;
  69. if ((chipId < gChipInfoArray[left].chipId) || (chipId > gChipInfoArray[right].chipId))
  70. return index;
  71. middle = (left + right) / 2;
  72. while (left <= right) {
  73. if (chipId > gChipInfoArray[middle].chipId) {
  74. left = middle + 1;
  75. } else if (chipId < gChipInfoArray[middle].chipId) {
  76. right = middle - 1;
  77. } else {
  78. index = middle;
  79. break;
  80. }
  81. middle = (left + right) / 2;
  82. }
  83. if (0 > index)
  84. WMT_DETECT_ERR_FUNC("no supported chipid found\n");
  85. else
  86. WMT_DETECT_INFO_FUNC("index:%d, chipId:0x%x\n", index, gChipInfoArray[index].chipId);
  87. return index;
  88. }
  89. int hif_sdio_match_chipid_by_dev_id(const struct sdio_device_id *id)
  90. {
  91. int maxIndex = sizeof(gChipInfoArray) / sizeof(gChipInfoArray[0]);
  92. int index = 0;
  93. struct sdio_device_id *localId = NULL;
  94. int chipId = -1;
  95. for (index = 0; index < maxIndex; index++) {
  96. localId = &(gChipInfoArray[index].deviceId);
  97. if ((localId->vendor == id->vendor) && (localId->device == id->device)) {
  98. chipId = gChipInfoArray[index].chipId;
  99. WMT_DETECT_INFO_FUNC
  100. ("valid chipId found, index(%d), vendor id(0x%x), device id(0x%x), chip id(0x%x)\n", index,
  101. localId->vendor, localId->device, chipId);
  102. gComboChipId = chipId;
  103. mtk_wcn_wmt_set_chipid(gComboChipId);
  104. break;
  105. }
  106. }
  107. if (0 > chipId) {
  108. WMT_DETECT_ERR_FUNC("No valid chipId found, vendor id(0x%x), device id(0x%x)\n", id->vendor,
  109. id->device);
  110. }
  111. return chipId;
  112. }
  113. int sdio_detect_query_chipid(int waitFlag)
  114. {
  115. unsigned int timeSlotMs = 200;
  116. unsigned int maxTimeSlot = 15;
  117. unsigned int counter = 0;
  118. /* gComboChipId = 0x6628; */
  119. if (0 == waitFlag)
  120. return gComboChipId;
  121. if (0 <= hif_sdio_is_chipid_valid(gComboChipId))
  122. return gComboChipId;
  123. while (counter < maxTimeSlot) {
  124. if (0 <= hif_sdio_is_chipid_valid(gComboChipId))
  125. break;
  126. msleep(timeSlotMs);
  127. counter++;
  128. }
  129. return gComboChipId;
  130. }
  131. int sdio_detect_do_autok(int chipId)
  132. {
  133. int i_ret = 0;
  134. #if MTK_HIF_SDIO_AUTOK_ENABLED
  135. #if 0
  136. BOOTMODE boot_mode;
  137. boot_mode = get_boot_mode();
  138. if (boot_mode == META_BOOT) {
  139. WMT_DETECT_INFO_FUNC("omit autok in meta mode\n");
  140. return 0;
  141. }
  142. #endif
  143. if (0x6630 == chipId) {
  144. #ifdef CONFIG_SDIOAUTOK_SUPPORT
  145. if (NULL != g_func) {
  146. WMT_DETECT_INFO_FUNC("wait_sdio_autok_ready++\n");
  147. i_ret = wait_sdio_autok_ready(g_func->card->host);
  148. WMT_DETECT_INFO_FUNC("wait_sdio_autok_ready--\n");
  149. if (0 == i_ret) {
  150. WMT_DETECT_INFO_FUNC("wait_sdio_autok_ready return success\n");
  151. } else {
  152. WMT_DETECT_INFO_FUNC("wait_sdio_autok_ready return fail, i_ret:%d\n", i_ret);
  153. gComboChipId = -1;
  154. }
  155. } else {
  156. WMT_DETECT_INFO_FUNC("g_func NULL, omit autok\n");
  157. }
  158. #else
  159. i_ret = 0;
  160. WMT_DETECT_INFO_FUNC("MTK_SDIOAUTOK_SUPPORT not defined\n");
  161. #endif
  162. } else {
  163. WMT_DETECT_INFO_FUNC("MT%x does not support SDIO3.0 autoK is not needed\n", chipId);
  164. }
  165. #else
  166. i_ret = 0;
  167. WMT_DETECT_INFO_FUNC("MTK_HIF_SDIO_AUTOK_ENABLED is not defined\n");
  168. #endif
  169. return i_ret;
  170. }
  171. /*!
  172. * \brief hif_sdio probe function
  173. *
  174. * hif_sdio probe function called by mmc driver when any matched SDIO function
  175. * is detected by it.
  176. *
  177. * \param func
  178. * \param id
  179. *
  180. * \retval 0 register successfully
  181. * \retval < 0 list error code here
  182. */
  183. static int sdio_detect_probe(struct sdio_func *func, const struct sdio_device_id *id)
  184. {
  185. int chipId = 0;
  186. WMT_DETECT_INFO_FUNC("vendor(0x%x) device(0x%x) num(0x%x)\n", func->vendor, func->device, func->num);
  187. chipId = hif_sdio_match_chipid_by_dev_id(id);
  188. if ((0x6630 == chipId) && (1 == func->num)) {
  189. int ret = 0;
  190. g_func = func;
  191. WMT_DETECT_INFO_FUNC("autok function detected, func:0x%p\n", g_func);
  192. sdio_claim_host(func);
  193. ret = sdio_enable_func(func);
  194. sdio_release_host(func);
  195. if (ret)
  196. WMT_DETECT_ERR_FUNC("sdio_enable_func failed!\n");
  197. }
  198. return 0;
  199. }
  200. static void sdio_detect_remove(struct sdio_func *func)
  201. {
  202. if (g_func == func) {
  203. sdio_claim_host(func);
  204. sdio_disable_func(func);
  205. sdio_release_host(func);
  206. g_func = NULL;
  207. }
  208. WMT_DETECT_INFO_FUNC("do sdio remove\n");
  209. }
  210. int sdio_detect_init(void)
  211. {
  212. int ret = -1;
  213. /* register to mmc driver */
  214. ret = sdio_register_driver(&mtk_sdio_client_drv);
  215. WMT_DETECT_INFO_FUNC("sdio_register_driver() ret=%d\n", ret);
  216. return 0;
  217. }
  218. int sdio_detect_exit(void)
  219. {
  220. g_func = NULL;
  221. /* register to mmc driver */
  222. sdio_unregister_driver(&mtk_sdio_client_drv);
  223. WMT_DETECT_INFO_FUNC("sdio_unregister_driver\n");
  224. return 0;
  225. }