2 #include "hif_sdio_chrdev.h"
6 static int hif_sdio_proc(void *pvData
);
7 static int hif_sdio_open(struct inode
*inode
, struct file
*file
);
8 static int hif_sdio_release(struct inode
*inode
, struct file
*file
);
9 static long hif_sdio_unlocked_ioctl(struct file
*filp
, unsigned int cmd
, unsigned long arg
);
10 static ssize_t
hif_sdio_read(struct file
*filp
, char __user
*buf
, size_t count
, loff_t
*f_pos
);
14 UINT32 hifSdioMajor
= 0;
16 #define COMBO_IOC_MAGIC 'h'
17 #define COMBO_IOCTL_GET_CHIP_ID _IOR(COMBO_IOC_MAGIC, 0, int)
18 #define COMBO_IOCTL_SET_CHIP_ID _IOW(COMBO_IOC_MAGIC, 1, int)
20 MTK_WCN_HIF_SDIO_CHIP_INFO gChipInfoArray
[] = {
21 /* MT6620 *//* Not an SDIO standard class device */
22 {{SDIO_DEVICE(0x037A, 0x020A)}, 0x6620}, /* SDIO1:FUNC1:WIFI */
23 {{SDIO_DEVICE(0x037A, 0x020B)}, 0x6620}, /* SDIO2:FUNC1:BT+FM+GPS */
24 {{SDIO_DEVICE(0x037A, 0x020C)}, 0x6620}, /* 2-function (SDIO2:FUNC1:BT+FM+GPS, FUNC2:WIFI) */
26 /* MT6628 *//* SDIO1: Wi-Fi, SDIO2: BGF */
27 {{SDIO_DEVICE(0x037A, 0x6628)}, 0x6628},
33 struct file_operations hifDevOps
= {
35 .open
= hif_sdio_open
,
36 .release
= hif_sdio_release
,
37 .unlocked_ioctl
= hif_sdio_unlocked_ioctl
,
38 .read
= hif_sdio_read
,
41 struct class *pHifClass
= NULL
;
42 struct device
*pHifDev
= NULL
;
43 PUINT8 HifClassName
= "hifsdiod";
44 PUINT8 kObjName
= "hifsdiod";
47 struct task_struct
*gConIdQueryThread
;
48 wait_queue_head_t gHifsdiodEvent
;
50 /* OSAL_THREAD gConIdQueryThread; */
51 /* OSAL_EVENT gHifsdiodEvent; */
52 PUINT8 gConIdQueryName
= "consys-id-query";
53 INT32 gComboChipId
= -1;
57 INT32
hifsdiod_start(VOID
)
60 init_waitqueue_head(&gHifsdiodEvent
);
62 osal_event_init(&gHifsdiodEvent
);
63 gConIdQueryThread
.pThreadData
= NULL
;
64 gConIdQueryThread
.pThreadFunc
= (size_t *) hif_sdio_proc
;
65 osal_memcpy(gConIdQueryThread
.threadName
, gConIdQueryName
, osal_strlen(gConIdQueryName
));
68 iRet
= osal_thread_create(&gConIdQueryThread
);
70 HIF_SDIO_ERR_FUNC("osal_thread_create fail...\n");
74 gConIdQueryThread
= kthread_create(hif_sdio_proc
, NULL
, gConIdQueryName
);
75 if (NULL
== gConIdQueryThread
) {
76 HIF_SDIO_ERR_FUNC("osal_thread_create fail...\n");
82 /* Start STPd thread */
83 iRet
= osal_thread_run(&gConIdQueryThread
);
85 HIF_SDIO_ERR_FUNC("osal_thread_run FAILS\n");
89 if (gConIdQueryThread
) {
90 wake_up_process(gConIdQueryThread
);
96 HIF_SDIO_INFO_FUNC("succeed\n");
101 HIF_SDIO_ERR_FUNC("failed\n");
106 INT32
hifsdiod_stop(VOID
)
108 if (gConIdQueryThread
) {
109 HIF_SDIO_INFO_FUNC("inform hifsdiod exit..\n");
110 kthread_stop(gConIdQueryThread
);
111 gConIdQueryThread
= NULL
;
117 static int hif_sdio_proc(void *pvData
)
119 while (!kthread_should_stop()) {
120 /* HIF_SDIO_INFO_FUNC("enter sleep.\n"); */
121 osal_sleep_ms(10000);
122 /* HIF_SDIO_INFO_FUNC("wakeup\n"); */
124 HIF_SDIO_INFO_FUNC("hifsdiod exit.\n");
129 static int hif_sdio_open(struct inode
*inode
, struct file
*file
)
131 HIF_SDIO_INFO_FUNC(" ++\n");
132 HIF_SDIO_INFO_FUNC(" --\n");
136 static int hif_sdio_release(struct inode
*inode
, struct file
*file
)
138 HIF_SDIO_INFO_FUNC(" ++\n");
139 HIF_SDIO_INFO_FUNC(" --\n");
145 static ssize_t
hif_sdio_read(struct file
*filp
, char __user
*buf
, size_t count
, loff_t
*f_pos
)
147 HIF_SDIO_INFO_FUNC(" ++\n");
148 HIF_SDIO_INFO_FUNC(" --\n");
153 static long hif_sdio_unlocked_ioctl(struct file
*filp
, unsigned int cmd
, unsigned long arg
)
157 HIF_SDIO_DBG_FUNC("cmd (%d)\n", cmd
);
160 case COMBO_IOCTL_GET_CHIP_ID
:
161 gComboChipId
= 0x6628;
162 retval
= gComboChipId
;
163 HIF_SDIO_INFO_FUNC("get combo chip id: 0x%x\n", gComboChipId
);
165 case COMBO_IOCTL_SET_CHIP_ID
:
167 HIF_SDIO_INFO_FUNC("set combo chip id to 0x%x\n", gComboChipId
);
170 HIF_SDIO_WARN_FUNC("unknown cmd (%d)\n", cmd
);
178 INT32
hif_sdio_is_chipid_valid(INT32 chipId
)
184 INT32 right
= ARRAY_SIZE(gChipInfoArray
) - 1;
185 if ((chipId
< gChipInfoArray
[left
].chipId
) || (chipId
> gChipInfoArray
[right
].chipId
))
188 middle
= (left
+ right
) / 2;
190 while (left
<= right
) {
191 if (chipId
> gChipInfoArray
[middle
].chipId
) {
193 } else if (chipId
< gChipInfoArray
[middle
].chipId
) {
199 middle
= (left
+ right
) / 2;
203 HIF_SDIO_ERR_FUNC("no supported chipid found\n");
205 HIF_SDIO_INFO_FUNC("index:%d, chipId:0x%x\n", index
, gChipInfoArray
[index
].chipId
);
211 INT32
hif_sdio_match_chipid_by_dev_id(const struct sdio_device_id
*id
)
213 INT32 maxIndex
= ARRAY_SIZE(gChipInfoArray
);
215 struct sdio_device_id
*localId
= NULL
;
217 for (index
= 0; index
< maxIndex
; index
++) {
218 localId
= &(gChipInfoArray
[index
].deviceId
);
219 if ((localId
->vendor
== id
->vendor
) && (localId
->device
== id
->device
)) {
220 chipId
= gChipInfoArray
[index
].chipId
;
222 ("valid chipId found, index(%d), vendor id(0x%x), device id(0x%x), chip id(0x%x)\n",
223 index
, localId
->vendor
, localId
->device
, chipId
);
224 gComboChipId
= chipId
;
229 HIF_SDIO_ERR_FUNC("No valid chipId found, vendor id(0x%x), device id(0x%x)\n",
230 id
->vendor
, id
->device
);
237 INT32
mtk_wcn_hif_sdio_query_chipid(INT32 waitFlag
)
239 UINT32 timeSlotMs
= 200;
240 UINT32 maxTimeSlot
= 15;
242 /* gComboChipId = 0x6628; */
245 if (0 <= hif_sdio_is_chipid_valid(gComboChipId
))
247 wmt_plat_pwr_ctrl(FUNC_ON
);
248 wmt_plat_sdio_ctrl(WMT_SDIO_SLOT_SDIO1
, FUNC_ON
);
249 while (counter
< maxTimeSlot
) {
250 if (0 <= hif_sdio_is_chipid_valid(gComboChipId
))
252 osal_sleep_ms(timeSlotMs
);
256 wmt_plat_sdio_ctrl(WMT_SDIO_SLOT_SDIO1
, FUNC_OFF
);
257 wmt_plat_pwr_ctrl(FUNC_OFF
);
260 EXPORT_SYMBOL(mtk_wcn_hif_sdio_query_chipid
);
262 INT32
mtk_wcn_hif_sdio_tell_chipid(INT32 chipId
)
265 gComboChipId
= chipId
;
266 HIF_SDIO_INFO_FUNC("set combo chip id to 0x%x\n", gComboChipId
);
270 EXPORT_SYMBOL(mtk_wcn_hif_sdio_tell_chipid
);
272 INT32
hif_sdio_create_dev_node(VOID
)
277 HIF_SDIO_DBG_FUNC("++");
278 iResult
= register_chrdev(hifSdioMajor
, kObjName
, &hifDevOps
);
280 HIF_SDIO_ERR_FUNC("register_chrdev failed.\n");
283 hifSdioMajor
= hifSdioMajor
== 0 ? iResult
: hifSdioMajor
;
284 HIF_SDIO_INFO_FUNC("register_chrdev succeed, mtk_jajor = %d\n", hifSdioMajor
);
285 pHifClass
= class_create(THIS_MODULE
, HifClassName
);
286 if (IS_ERR(pHifClass
)) {
287 HIF_SDIO_ERR_FUNC("class_create error\n");
291 device_create(pHifClass
, NULL
, MKDEV(hifSdioMajor
, 0), NULL
,
292 HifClassName
, "%d", 0);
293 if (IS_ERR(pHifDev
)) {
294 HIF_SDIO_ERR_FUNC("device_create error:%ld\n", PTR_ERR(pHifDev
));
297 HIF_SDIO_INFO_FUNC("device_create succeed\n");
306 INT32
hif_sdio_remove_dev_node(VOID
)
308 if (pHifDev
!= NULL
) {
309 device_destroy(pHifClass
, MKDEV(hifSdioMajor
, 0));
312 if (pHifClass
!= NULL
) {
313 class_destroy(pHifClass
);
317 if (hifSdioMajor
!= 0) {
318 unregister_chrdev(hifSdioMajor
, kObjName
);