2 * Copyright (C) 2011-2014 MediaTek Inc.
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.
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.
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/>.
18 #define DFT_TAG "[SDIO-DETECT]"
20 #include "wmt_detect.h"
22 #if MTK_HIF_SDIO_AUTOK_ENABLED
23 #include <mach/mt_boot.h>
26 unsigned int gComboChipId
= -1;
27 struct sdio_func
*g_func
= NULL
;
29 MTK_WCN_HIF_SDIO_CHIP_INFO gChipInfoArray
[] = {
30 /* MT6620 */ /* Not an SDIO standard class device */
31 { {SDIO_DEVICE(0x037A, 0x020A)}, 0x6620 }, /* SDIO1:FUNC1:WIFI */
32 { {SDIO_DEVICE(0x037A, 0x020B)}, 0x6620 }, /* SDIO2:FUNC1:BT+FM+GPS */
33 { {SDIO_DEVICE(0x037A, 0x020C)}, 0x6620 }, /* 2-function (SDIO2:FUNC1:BT+FM+GPS, FUNC2:WIFI) */
35 /* MT6628 */ /* SDIO1: Wi-Fi, SDIO2: BGF */
36 { {SDIO_DEVICE(0x037A, 0x6628)}, 0x6628},
38 /* MT6630 */ /* SDIO1: Wi-Fi, SDIO2: BGF */
39 { {SDIO_DEVICE(0x037A, 0x6630)}, 0x6630 },
44 /* Supported SDIO device table */
45 static const struct sdio_device_id mtk_sdio_id_tbl
[] = {
46 /* MT6618 */ /* Not an SDIO standard class device */
47 { SDIO_DEVICE(0x037A, 0x018A) }, /* SDIO1:WIFI */
48 { SDIO_DEVICE(0x037A, 0x018B) }, /* SDIO2:FUNC1:BT+FM */
49 { SDIO_DEVICE(0x037A, 0x018C) }, /* 2-function (SDIO2:FUNC1:BT+FM, FUNC2:WIFI) */
51 /* MT6619 */ /* Not an SDIO standard class device */
52 { SDIO_DEVICE(0x037A, 0x6619) }, /* SDIO2:FUNC1:BT+FM+GPS */
54 /* MT6620 */ /* Not an SDIO standard class device */
55 { SDIO_DEVICE(0x037A, 0x020A) }, /* SDIO1:FUNC1:WIFI */
56 { SDIO_DEVICE(0x037A, 0x020B) }, /* SDIO2:FUNC1:BT+FM+GPS */
57 { SDIO_DEVICE(0x037A, 0x020C) }, /* 2-function (SDIO2:FUNC1:BT+FM+GPS, FUNC2:WIFI) */
59 /* MT5921 */ /* Not an SDIO standard class device */
60 { SDIO_DEVICE(0x037A, 0x5921) },
62 /* MT6628 */ /* SDIO1: Wi-Fi, SDIO2: BGF */
63 { SDIO_DEVICE(0x037A, 0x6628) },
65 /* MT6630 */ /* SDIO1: Wi-Fi, SDIO2: BGF */
66 { SDIO_DEVICE(0x037A, 0x6630) },
67 { /* end: all zeroes */ },
70 static int sdio_detect_probe (
71 struct sdio_func
*func
,
72 const struct sdio_device_id
*id
75 static void sdio_detect_remove (
76 struct sdio_func
*func
79 static struct sdio_driver mtk_sdio_client_drv
= {
80 .name
= "mtk_sdio_client", /* MTK SDIO Client Driver */
81 .id_table
= mtk_sdio_id_tbl
, /* all supported struct sdio_device_id table */
82 .probe
= sdio_detect_probe
,
83 .remove
= sdio_detect_remove
,
86 static int hif_sdio_match_chipid_by_dev_id (const struct sdio_device_id
*id
);
89 int hif_sdio_is_chipid_valid (int chipId
)
95 int right
= sizeof (gChipInfoArray
) / sizeof (gChipInfoArray
[0]) - 1;
96 if ((chipId
< gChipInfoArray
[left
].chipId
) || (chipId
> gChipInfoArray
[right
].chipId
))
99 middle
= (left
+ right
) / 2;
101 while (left
<= right
)
103 if (chipId
> gChipInfoArray
[middle
].chipId
)
107 else if (chipId
< gChipInfoArray
[middle
].chipId
)
116 middle
= (left
+ right
) / 2;
121 WMT_DETECT_ERR_FUNC("no supported chipid found\n");
125 WMT_DETECT_INFO_FUNC("index:%d, chipId:0x%x\n", index
, gChipInfoArray
[index
].chipId
);
131 int hif_sdio_match_chipid_by_dev_id (const struct sdio_device_id
*id
)
133 int maxIndex
= sizeof (gChipInfoArray
) / sizeof (gChipInfoArray
[0]);
135 struct sdio_device_id
*localId
= NULL
;
137 for (index
= 0; index
< maxIndex
; index
++)
139 localId
= &(gChipInfoArray
[index
].deviceId
);
140 if ((localId
->vendor
== id
->vendor
) && (localId
->device
== id
->device
))
142 chipId
= gChipInfoArray
[index
].chipId
;
143 WMT_DETECT_INFO_FUNC("valid chipId found, index(%d), vendor id(0x%x), device id(0x%x), chip id(0x%x)\n", index
, localId
->vendor
, localId
->device
, chipId
);
144 gComboChipId
= chipId
;
145 mtk_wcn_wmt_set_chipid(gComboChipId
);
151 WMT_DETECT_ERR_FUNC("No valid chipId found, vendor id(0x%x), device id(0x%x)\n", id
->vendor
, id
->device
);
157 int sdio_detect_query_chipid(int waitFlag
)
159 unsigned int timeSlotMs
= 200;
160 unsigned int maxTimeSlot
= 15;
161 unsigned int counter
= 0;
162 //gComboChipId = 0x6628;
165 if (0 <= hif_sdio_is_chipid_valid(gComboChipId
))
168 while (counter
< maxTimeSlot
)
170 if (0 <= hif_sdio_is_chipid_valid(gComboChipId
))
179 int sdio_detect_do_autok(int chipId
)
183 #if MTK_HIF_SDIO_AUTOK_ENABLED
187 boot_mode
= get_boot_mode();
189 if (boot_mode
== META_BOOT
)
191 WMT_DETECT_INFO_FUNC("omit autok in meta mode\n");
195 if (0x6630 == chipId
)
197 #ifdef CONFIG_SDIOAUTOK_SUPPORT
200 WMT_DETECT_INFO_FUNC("wait_sdio_autok_ready++\n");
201 i_ret
= wait_sdio_autok_ready(g_func
->card
->host
);
202 WMT_DETECT_INFO_FUNC("wait_sdio_autok_ready--\n");
205 WMT_DETECT_INFO_FUNC("wait_sdio_autok_ready return success\n");
209 WMT_DETECT_INFO_FUNC("wait_sdio_autok_ready return fail, i_ret:%d\n", i_ret
);
215 WMT_DETECT_INFO_FUNC("g_func NULL, omit autok\n");
219 WMT_DETECT_INFO_FUNC("MTK_SDIOAUTOK_SUPPORT not defined\n");
224 WMT_DETECT_INFO_FUNC("MT%x does not support SDIO3.0 autoK is not needed\n", chipId
);
228 WMT_DETECT_INFO_FUNC("MTK_HIF_SDIO_AUTOK_ENABLED is not defined\n");
235 * \brief hif_sdio probe function
237 * hif_sdio probe function called by mmc driver when any matched SDIO function
243 * \retval 0 register successfully
244 * \retval < 0 list error code here
246 static int sdio_detect_probe (
247 struct sdio_func
*func
,
248 const struct sdio_device_id
*id
252 WMT_DETECT_INFO_FUNC("vendor(0x%x) device(0x%x) num(0x%x)\n", func
->vendor
, func
->device
, func
->num
);
253 chipId
= hif_sdio_match_chipid_by_dev_id(id
);
255 if ((0x6630 == chipId
) && (1 == func
->num
))
259 WMT_DETECT_INFO_FUNC("autok function detected, func:0x%p\n", g_func
);
261 sdio_claim_host(func
);
262 ret
= sdio_enable_func(func
);
263 sdio_release_host(func
);
265 WMT_DETECT_ERR_FUNC("sdio_enable_func failed!\n");
273 static void sdio_detect_remove (
274 struct sdio_func
*func
279 sdio_claim_host(func
);
280 sdio_disable_func(func
);
281 sdio_release_host(func
);
284 WMT_DETECT_INFO_FUNC("do sdio remove\n");
290 int sdio_detect_init(void)
293 //register to mmc driver
294 ret
= sdio_register_driver(&mtk_sdio_client_drv
);
295 WMT_DETECT_INFO_FUNC("sdio_register_driver() ret=%d\n", ret
);
300 int sdio_detect_exit(void)
303 //register to mmc driver
304 sdio_unregister_driver(&mtk_sdio_client_drv
);
305 WMT_DETECT_INFO_FUNC("sdio_unregister_driver\n");