1 /*
2  * sdio_adapter.c
3  *
4  * linux sdio driver implement.
5  *
6  * Copyright (c) 2020-2023 Huawei Device Co., Ltd.
7  *
8  * This software is licensed under the terms of the GNU General Public
9  * License version 2, as published by the Free Software Foundation, and
10  * may be copied, distributed, and modified under those terms.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  */
18 
19 #include <linux/mmc/card.h>
20 #include <linux/mmc/core.h>
21 #include <linux/mmc/host.h>
22 #include <linux/mmc/sdio_func.h>
23 #include "device_resource_if.h"
24 #include "mmc_corex.h"
25 #include "mmc_sdio.h"
26 
27 #define HDF_LOG_TAG sdio_adapter_c
28 
29 #define DATA_LEN_ONE_BYTE 1
30 #define DATA_LEN_TWO_BYTES 2
31 #define DATA_LEN_FOUR_BYTES 4
32 #define MMC_SLOT_NUM 3
33 #define SDIO_RESCAN_WAIT_TIME 40
34 
35 struct mmc_host *GetMmcHost(int32_t slot);
36 void SdioRescan(int32_t slot);
37 
38 enum SleepTime {
39     MS_10 = 10,
40     MS_50 = 50,
41 };
42 
LinuxSdioGetFunc(const struct SdioDevice * dev)43 static struct sdio_func *LinuxSdioGetFunc(const struct SdioDevice *dev)
44 {
45     if (dev == NULL) {
46         HDF_LOGE("LinuxSdioGetFunc: dev is null.");
47         return NULL;
48     }
49     return (struct sdio_func *)dev->sd.mmc.priv;
50 }
51 
LinuxSdioIncrAddrReadBytes(struct SdioDevice * dev,uint8_t * data,uint32_t addr,uint32_t size)52 static int32_t LinuxSdioIncrAddrReadBytes(struct SdioDevice *dev,
53     uint8_t *data, uint32_t addr, uint32_t size)
54 {
55     struct sdio_func *func = LinuxSdioGetFunc(dev);
56     int32_t ret = HDF_SUCCESS;
57     uint16_t *output16 = NULL;
58     uint32_t *output32 = NULL;
59 
60     if (func == NULL) {
61         HDF_LOGE("LinuxSdioIncrAddrReadBytes: func is NULL.");
62         return HDF_ERR_INVALID_OBJECT;
63     }
64     if ((data == NULL) || (size == 0)) {
65         HDF_LOGE("LinuxSdioIncrAddrReadBytes: data or size is invalid.");
66         return HDF_ERR_INVALID_PARAM;
67     }
68 
69     if (size == DATA_LEN_ONE_BYTE) {
70         *data = sdio_readb(func, addr, &ret);
71         return ret;
72     }
73     if (size == DATA_LEN_TWO_BYTES) {
74         output16 = (uint16_t *)data;
75         *output16 = sdio_readw(func, addr, &ret);
76         return ret;
77     }
78     if (size == DATA_LEN_FOUR_BYTES) {
79         output32 = (uint32_t *)data;
80         *output32 = sdio_readl(func, addr, &ret);
81         return ret;
82     }
83     return sdio_memcpy_fromio(func, data, addr, size);
84 }
85 
LinuxSdioIncrAddrWriteBytes(struct SdioDevice * dev,uint8_t * data,uint32_t addr,uint32_t size)86 static int32_t LinuxSdioIncrAddrWriteBytes(struct SdioDevice *dev,
87     uint8_t *data, uint32_t addr, uint32_t size)
88 {
89     int32_t ret = HDF_SUCCESS;
90     struct sdio_func *func = LinuxSdioGetFunc(dev);
91 
92     if (func == NULL) {
93         HDF_LOGE("LinuxSdioIncrAddrWriteBytes: func is NULL.");
94         return HDF_ERR_INVALID_OBJECT;
95     }
96     if ((data == NULL) || (size == 0)) {
97         HDF_LOGE("LinuxSdioIncrAddrWriteBytes: data or size is invalid.");
98         return HDF_ERR_INVALID_PARAM;
99     }
100 
101     if (size == DATA_LEN_ONE_BYTE) {
102         sdio_writeb(func, *data, addr, &ret);
103         return ret;
104     }
105     if (size == DATA_LEN_TWO_BYTES) {
106         sdio_writew(func, *(uint16_t *)data, addr, &ret);
107         return ret;
108     }
109     if (size == DATA_LEN_FOUR_BYTES) {
110         sdio_writel(func, *(uint32_t *)data, addr, &ret);
111         return ret;
112     }
113     return sdio_memcpy_toio(func, addr, data, size);
114 }
115 
LinuxSdioFixedAddrReadBytes(struct SdioDevice * dev,uint8_t * data,uint32_t addr,uint32_t size,uint32_t scatterLen)116 static int32_t LinuxSdioFixedAddrReadBytes(struct SdioDevice *dev,
117     uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen)
118 {
119     struct sdio_func *func = LinuxSdioGetFunc(dev);
120 
121     if (func == NULL) {
122         HDF_LOGE("LinuxSdioFixedAddrReadBytes: func is NULL.");
123         return HDF_ERR_INVALID_OBJECT;
124     }
125     if ((data == NULL) || (size == 0)) {
126         HDF_LOGE("LinuxSdioFixedAddrReadBytes: data or size is invalid.");
127         return HDF_ERR_INVALID_PARAM;
128     }
129 
130     if (scatterLen > 0) {
131         HDF_LOGE("LinuxSdioFixedAddrReadBytes: not support!");
132         return HDF_ERR_NOT_SUPPORT;
133     }
134     return sdio_readsb(func, data, addr, size);
135 }
136 
LinuxSdioFixedAddrWriteBytes(struct SdioDevice * dev,uint8_t * data,uint32_t addr,uint32_t size,uint32_t scatterLen)137 static int32_t LinuxSdioFixedAddrWriteBytes(struct SdioDevice *dev,
138     uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen)
139 {
140     struct sdio_func *func = LinuxSdioGetFunc(dev);
141 
142     if (func == NULL) {
143         HDF_LOGE("LinuxSdioFixedAddrWriteBytes: func is NULL.");
144         return HDF_ERR_INVALID_OBJECT;
145     }
146     if ((data == NULL) || (size == 0)) {
147         HDF_LOGE("LinuxSdioFixedAddrReadBytes: data or size is invalid.");
148         return HDF_ERR_INVALID_PARAM;
149     }
150 
151     if (scatterLen > 0) {
152         HDF_LOGE("LinuxSdioFixedAddrWriteBytes: not support!");
153         return HDF_ERR_NOT_SUPPORT;
154     }
155     return sdio_writesb(func, addr, data, size);
156 }
157 
LinuxSdioFunc0ReadBytes(struct SdioDevice * dev,uint8_t * data,uint32_t addr,uint32_t size)158 static int32_t LinuxSdioFunc0ReadBytes(struct SdioDevice *dev,
159     uint8_t *data, uint32_t addr, uint32_t size)
160 {
161     int32_t ret = HDF_SUCCESS;
162     struct sdio_func *func = LinuxSdioGetFunc(dev);
163 
164     if (func == NULL) {
165         HDF_LOGE("LinuxSdioFunc0ReadBytes: func is NULL.");
166         return HDF_ERR_INVALID_OBJECT;
167     }
168     if ((data == NULL) || (size == 0)) {
169         HDF_LOGE("LinuxSdioFunc0ReadBytes: data or size is invalid.");
170         return HDF_ERR_INVALID_PARAM;
171     }
172 
173     *data = sdio_f0_readb(func, addr, &ret);
174     return ret;
175 }
176 
LinuxSdioFunc0WriteBytes(struct SdioDevice * dev,uint8_t * data,uint32_t addr,uint32_t size)177 static int32_t LinuxSdioFunc0WriteBytes(struct SdioDevice *dev,
178     uint8_t *data, uint32_t addr, uint32_t size)
179 {
180     int32_t ret = HDF_SUCCESS;
181     struct sdio_func *func = LinuxSdioGetFunc(dev);
182 
183     if (func == NULL) {
184         HDF_LOGE("LinuxSdioFunc0WriteBytes: func is NULL.");
185         return HDF_ERR_INVALID_OBJECT;
186     }
187     if ((data == NULL) || (size == 0)) {
188         HDF_LOGE("LinuxSdioFunc0WriteBytes: data or size is invalid.");
189         return HDF_ERR_INVALID_PARAM;
190     }
191 
192     sdio_f0_writeb(func, *data, addr, &ret);
193     return ret;
194 }
195 
LinuxSdioSetBlockSize(struct SdioDevice * dev,uint32_t blockSize)196 static int32_t LinuxSdioSetBlockSize(struct SdioDevice *dev, uint32_t blockSize)
197 {
198     struct sdio_func *func = LinuxSdioGetFunc(dev);
199 
200     if (func == NULL) {
201         HDF_LOGE("LinuxSdioSetBlockSize, func is NULL.");
202         return HDF_ERR_INVALID_OBJECT;
203     }
204     return sdio_set_block_size(func, blockSize);
205 }
206 
LinuxSdioGetCommonInfo(struct SdioDevice * dev,SdioCommonInfo * info,uint32_t infoType)207 static int32_t LinuxSdioGetCommonInfo(struct SdioDevice *dev,
208     SdioCommonInfo *info, uint32_t infoType)
209 {
210     struct sdio_func *func = LinuxSdioGetFunc(dev);
211 
212     if (func == NULL) {
213         HDF_LOGE("LinuxSdioGetCommonInfo: func is NULL.");
214         return HDF_ERR_INVALID_OBJECT;
215     }
216     if (info == NULL) {
217         HDF_LOGE("LinuxSdioGetCommonInfo: info is null.");
218         return HDF_ERR_INVALID_PARAM;
219     }
220     if (infoType != SDIO_FUNC_INFO) {
221         HDF_LOGE("LinuxSdioGetCommonInfo: cur type %u is not support.", infoType);
222         return HDF_ERR_NOT_SUPPORT;
223     }
224 
225     if (func->card == NULL) {
226         HDF_LOGE("LinuxSdioGetCommonInfo fail, card is null.");
227         return HDF_ERR_INVALID_PARAM;
228     }
229     if (func->card->host == NULL) {
230         HDF_LOGE("LinuxSdioGetCommonInfo fail, host is null.");
231         return HDF_ERR_INVALID_PARAM;
232     }
233     info->funcInfo.enTimeout = func->enable_timeout;
234     info->funcInfo.maxBlockNum = func->card->host->max_blk_count;
235     info->funcInfo.maxBlockSize = func->card->host->max_blk_size;
236     info->funcInfo.maxRequestSize = func->card->host->max_req_size;
237     info->funcInfo.funcNum = func->num;
238     info->funcInfo.irqCap = func->card->host->caps & MMC_CAP_SDIO_IRQ;
239     info->funcInfo.data = func;
240     return HDF_SUCCESS;
241 }
242 
LinuxSdioSetCommonInfo(struct SdioDevice * dev,SdioCommonInfo * info,uint32_t infoType)243 static int32_t LinuxSdioSetCommonInfo(struct SdioDevice *dev,
244     SdioCommonInfo *info, uint32_t infoType)
245 {
246     struct sdio_func *func = LinuxSdioGetFunc(dev);
247 
248     if (func == NULL) {
249         HDF_LOGE("LinuxSdioSetCommonInfo: func is NULL.");
250         return HDF_ERR_INVALID_OBJECT;
251     }
252     if (info == NULL) {
253         HDF_LOGE("LinuxSdioSetCommonInfo: info is null.");
254         return HDF_ERR_INVALID_PARAM;
255     }
256     if (infoType != SDIO_FUNC_INFO) {
257         HDF_LOGE("LinuxSdioSetCommonInfo: cur type %u is not support.", infoType);
258         return HDF_ERR_NOT_SUPPORT;
259     }
260 
261     if (func->card == NULL) {
262         HDF_LOGE("LinuxSdioSetCommonInfo fail, card is null.");
263         return HDF_ERR_INVALID_PARAM;
264     }
265     if (func->card->host == NULL) {
266         HDF_LOGE("LinuxSdioSetCommonInfo fail, host is null.");
267         return HDF_ERR_INVALID_PARAM;
268     }
269     func->enable_timeout = info->funcInfo.enTimeout;
270     func->card->host->max_blk_count = info->funcInfo.maxBlockNum;
271     func->card->host->max_blk_size = info->funcInfo.maxBlockSize;
272     func->card->host->max_req_size = info->funcInfo.maxRequestSize;
273     func->num = info->funcInfo.funcNum;
274     return HDF_SUCCESS;
275 }
276 
LinuxSdioFlushData(struct SdioDevice * dev)277 static int32_t LinuxSdioFlushData(struct SdioDevice *dev)
278 {
279     struct sdio_func *func = LinuxSdioGetFunc(dev);
280 
281     if (func == NULL) {
282         HDF_LOGE("LinuxSdioFlushData: func is NULL.");
283         return HDF_ERR_INVALID_OBJECT;
284     }
285     if (func->card == NULL) {
286         HDF_LOGE("LinuxSdioFlushData: card is NULL.");
287         return HDF_ERR_INVALID_OBJECT;
288     }
289 
290     return mmc_sw_reset(func->card->host);
291 }
292 
LinuxSdioClaimHost(struct SdioDevice * dev)293 static int32_t LinuxSdioClaimHost(struct SdioDevice *dev)
294 {
295     struct sdio_func *func = LinuxSdioGetFunc(dev);
296 
297     if (func == NULL) {
298         HDF_LOGE("LinuxSdioClaimHost: func is NULL.");
299         return HDF_ERR_INVALID_OBJECT;
300     }
301     sdio_claim_host(func);
302     return HDF_SUCCESS;
303 }
304 
LinuxSdioReleaseHost(struct SdioDevice * dev)305 static int32_t LinuxSdioReleaseHost(struct SdioDevice *dev)
306 {
307     struct sdio_func *func = LinuxSdioGetFunc(dev);
308 
309     if (func == NULL) {
310         HDF_LOGE("LinuxSdioReleaseHost: func is NULL.");
311         return HDF_ERR_INVALID_OBJECT;
312     }
313     sdio_release_host(func);
314     return HDF_SUCCESS;
315 }
316 
LinuxSdioEnableFunc(struct SdioDevice * dev)317 static int32_t LinuxSdioEnableFunc(struct SdioDevice *dev)
318 {
319     struct sdio_func *func = LinuxSdioGetFunc(dev);
320 
321     if (func == NULL) {
322         HDF_LOGE("LinuxSdioEnableFunc: func is NULL.");
323         return HDF_ERR_INVALID_OBJECT;
324     }
325     return sdio_enable_func(func);
326 }
327 
LinuxSdioDisableFunc(struct SdioDevice * dev)328 static int32_t LinuxSdioDisableFunc(struct SdioDevice *dev)
329 {
330     struct sdio_func *func = LinuxSdioGetFunc(dev);
331 
332     if (func == NULL) {
333         HDF_LOGE("LinuxSdioDisableFunc: func is NULL.");
334         return HDF_ERR_INVALID_OBJECT;
335     }
336     return sdio_disable_func(func);
337 }
338 
LinuxSdioClaimIrq(struct SdioDevice * dev,SdioIrqHandler * handler)339 static int32_t LinuxSdioClaimIrq(struct SdioDevice *dev, SdioIrqHandler *handler)
340 {
341     struct sdio_func *func = LinuxSdioGetFunc(dev);
342 
343     if (func == NULL) {
344         HDF_LOGE("LinuxSdioClaimIrq: func is NULL.");
345         return HDF_ERR_INVALID_OBJECT;
346     }
347     if (handler == NULL) {
348         HDF_LOGE("LinuxSdioClaimIrq: handler is null.");
349         return HDF_ERR_INVALID_PARAM;
350     }
351     return sdio_claim_irq(func, (sdio_irq_handler_t *)handler);
352 }
353 
LinuxSdioReleaseIrq(struct SdioDevice * dev)354 static int32_t LinuxSdioReleaseIrq(struct SdioDevice *dev)
355 {
356     struct sdio_func *func = LinuxSdioGetFunc(dev);
357 
358     if (func == NULL) {
359         HDF_LOGE("LinuxSdioReleaseIrq: func is NULL.");
360         return HDF_ERR_INVALID_OBJECT;
361     }
362     return sdio_release_irq(func);
363 }
364 
LinuxSdioSearchFunc(uint32_t funcNum,uint16_t vendorId,uint16_t deviceId)365 static struct sdio_func *LinuxSdioSearchFunc(uint32_t funcNum, uint16_t vendorId, uint16_t deviceId)
366 {
367     struct mmc_card *card = NULL;
368     struct mmc_host *host = NULL;
369     struct sdio_func *func = NULL;
370     uint32_t i;
371     uint32_t j;
372 
373     for (i = 0; i < MMC_SLOT_NUM; i++) {
374         host = GetMmcHost(i);
375         if (host == NULL) {
376             continue;
377         }
378         card = host->card;
379         if (card == NULL) {
380             continue;
381         }
382         for (j = 0; j <= card->sdio_funcs; j++) {
383             func = card->sdio_func[j];
384             if ((func != NULL) &&
385                 (func->num == funcNum) &&
386                 (func->vendor == vendorId) &&
387                 (func->device == deviceId)) {
388                 HDF_LOGD("LinuxSdioSearchFunc: find func!");
389                 return func;
390             }
391         }
392     }
393 
394     HDF_LOGE("LinuxSdioSearchFunc: get sdio func fail!");
395     return NULL;
396 }
397 
LinuxSdioFindFunc(struct SdioDevice * dev,struct SdioFunctionConfig * configData)398 static int32_t LinuxSdioFindFunc(struct SdioDevice *dev, struct SdioFunctionConfig *configData)
399 {
400     if (dev == NULL || configData == NULL) {
401         HDF_LOGE("LinuxSdioFindFunc: dev or configData is NULL.");
402         return HDF_ERR_INVALID_OBJECT;
403     }
404 
405     dev->sd.mmc.priv = LinuxSdioSearchFunc(configData->funcNr, configData->vendorId, configData->deviceId);
406     if (dev->sd.mmc.priv == NULL) {
407         HDF_LOGE("LinuxSdioFindFunc: LinuxSdioSearchFunc fail.");
408         return HDF_ERR_NOT_SUPPORT;
409     }
410     return HDF_SUCCESS;
411 }
412 
413 static struct SdioDeviceOps g_sdioDeviceOps = {
414     .incrAddrReadBytes = LinuxSdioIncrAddrReadBytes,
415     .incrAddrWriteBytes = LinuxSdioIncrAddrWriteBytes,
416     .fixedAddrReadBytes = LinuxSdioFixedAddrReadBytes,
417     .fixedAddrWriteBytes = LinuxSdioFixedAddrWriteBytes,
418     .func0ReadBytes = LinuxSdioFunc0ReadBytes,
419     .func0WriteBytes = LinuxSdioFunc0WriteBytes,
420     .setBlockSize = LinuxSdioSetBlockSize,
421     .getCommonInfo = LinuxSdioGetCommonInfo,
422     .setCommonInfo = LinuxSdioSetCommonInfo,
423     .flushData = LinuxSdioFlushData,
424     .enableFunc = LinuxSdioEnableFunc,
425     .disableFunc = LinuxSdioDisableFunc,
426     .claimIrq = LinuxSdioClaimIrq,
427     .releaseIrq = LinuxSdioReleaseIrq,
428     .findFunc = LinuxSdioFindFunc,
429     .claimHost = LinuxSdioClaimHost,
430     .releaseHost = LinuxSdioReleaseHost,
431 };
432 
LinuxSdioRescanFinish(struct MmcCntlr * cntlr)433 static bool LinuxSdioRescanFinish(struct MmcCntlr *cntlr)
434 {
435     struct mmc_host *host = NULL;
436     struct mmc_card *card = NULL;
437 
438     host = GetMmcHost(cntlr->index);
439     if (host == NULL) {
440         return false;
441     }
442 
443     card = host->card;
444     if (card == NULL) {
445         return false;
446     }
447     if (card->sdio_funcs > 0) {
448         return true;
449     }
450     return false;
451 }
452 
LinuxSdioRescan(struct MmcCntlr * cntlr)453 static int32_t LinuxSdioRescan(struct MmcCntlr *cntlr)
454 {
455     bool rescanFinish = false;
456     uint32_t count = 0;
457 
458     if (cntlr == NULL) {
459         HDF_LOGE("LinuxSdioRescan: cntlr is NULL.");
460         return HDF_ERR_INVALID_OBJECT;
461     }
462 
463     SdioRescan(cntlr->index);
464     while (rescanFinish == false && count < SDIO_RESCAN_WAIT_TIME) {
465         OsalMSleep(MS_50);
466         count++;
467         rescanFinish = LinuxSdioRescanFinish(cntlr);
468     }
469 
470     if (rescanFinish == false) {
471         HDF_LOGE("LinuxSdioRescan: fail!");
472         return HDF_FAILURE;
473     }
474 
475     OsalMSleep(MS_10);
476     return HDF_SUCCESS;
477 }
478 
479 struct MmcCntlrOps g_sdioCntlrOps = {
480     .rescanSdioDev = LinuxSdioRescan,
481 };
482 
LinuxSdioDeleteCntlr(struct MmcCntlr * cntlr)483 static void LinuxSdioDeleteCntlr(struct MmcCntlr *cntlr)
484 {
485     if (cntlr == NULL) {
486         return;
487     }
488 
489     if (cntlr->curDev != NULL) {
490         MmcDeviceRemove(cntlr->curDev);
491         OsalMemFree(cntlr->curDev);
492     }
493     MmcCntlrRemove(cntlr);
494     OsalMemFree(cntlr);
495 }
496 
LinuxSdioCntlrParse(struct MmcCntlr * cntlr,struct HdfDeviceObject * obj)497 static int32_t LinuxSdioCntlrParse(struct MmcCntlr *cntlr, struct HdfDeviceObject *obj)
498 {
499     const struct DeviceResourceNode *node = NULL;
500     struct DeviceResourceIface *drsOps = NULL;
501     int32_t ret;
502 
503     if (obj == NULL || cntlr == NULL) {
504         HDF_LOGE("LinuxSdioCntlrParse: input para is NULL.");
505         return HDF_FAILURE;
506     }
507 
508     node = obj->property;
509     if (node == NULL) {
510         HDF_LOGE("LinuxSdioCntlrParse: drs node is NULL.");
511         return HDF_FAILURE;
512     }
513     drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
514     if (drsOps == NULL || drsOps->GetUint16 == NULL || drsOps->GetUint32 == NULL) {
515         HDF_LOGE("LinuxSdioCntlrParse: invalid drs ops fail!");
516         return HDF_FAILURE;
517     }
518 
519     ret = drsOps->GetUint16(node, "hostId", &(cntlr->index), 0);
520     if (ret != HDF_SUCCESS) {
521         HDF_LOGE("LinuxSdioCntlrParse: read hostIndex fail!");
522         return ret;
523     }
524     ret = drsOps->GetUint32(node, "devType", &(cntlr->devType), 0);
525     if (ret != HDF_SUCCESS) {
526         HDF_LOGE("LinuxSdioCntlrParse: read devType fail!");
527         return ret;
528     }
529     HDF_LOGD("LinuxSdioCntlrParse: hostIndex = %d, devType = %d.", cntlr->index, cntlr->devType);
530     return HDF_SUCCESS;
531 }
532 
LinuxSdioBind(struct HdfDeviceObject * obj)533 static int32_t LinuxSdioBind(struct HdfDeviceObject *obj)
534 {
535     struct MmcCntlr *cntlr = NULL;
536     int32_t ret;
537 
538     if (obj == NULL) {
539         HDF_LOGE("LinuxSdioBind: Fail, obj is NULL.");
540         return HDF_ERR_INVALID_OBJECT;
541     }
542 
543     cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr));
544     if (cntlr == NULL) {
545         HDF_LOGE("LinuxSdioBind: no mem for MmcCntlr.");
546         return HDF_ERR_MALLOC_FAIL;
547     }
548 
549     cntlr->ops = &g_sdioCntlrOps;
550     cntlr->hdfDevObj = obj;
551     obj->service = &cntlr->service;
552     /* init cntlr. */
553     ret = LinuxSdioCntlrParse(cntlr, obj);
554     if (ret != HDF_SUCCESS) {
555         HDF_LOGE("LinuxSdioBind: cntlr parse fail.");
556         goto _ERR;
557     }
558 
559     ret = MmcCntlrAdd(cntlr, false);
560     if (ret != HDF_SUCCESS) {
561         HDF_LOGE("LinuxSdioBind: cntlr add fail.");
562         goto _ERR;
563     }
564 
565     ret = MmcCntlrAllocDev(cntlr, (enum MmcDevType)cntlr->devType);
566     if (ret != HDF_SUCCESS) {
567         HDF_LOGE("LinuxSdioBind: alloc dev fail.");
568         goto _ERR;
569     }
570     MmcDeviceAddOps(cntlr->curDev, &g_sdioDeviceOps);
571     HDF_LOGD("LinuxSdioBind: Success!");
572     return HDF_SUCCESS;
573 
574 _ERR:
575     LinuxSdioDeleteCntlr(cntlr);
576     HDF_LOGE("LinuxSdioBind: Fail!");
577     return HDF_FAILURE;
578 }
579 
LinuxSdioInit(struct HdfDeviceObject * obj)580 static int32_t LinuxSdioInit(struct HdfDeviceObject *obj)
581 {
582     (void)obj;
583     HDF_LOGD("LinuxSdioInit: Success!");
584     return HDF_SUCCESS;
585 }
586 
LinuxSdioRelease(struct HdfDeviceObject * obj)587 static void LinuxSdioRelease(struct HdfDeviceObject *obj)
588 {
589     if (obj == NULL) {
590         return;
591     }
592     LinuxSdioDeleteCntlr((struct MmcCntlr *)obj->service);
593 }
594 
595 struct HdfDriverEntry g_sdioDriverEntry = {
596     .moduleVersion = 1,
597     .Bind = LinuxSdioBind,
598     .Init = LinuxSdioInit,
599     .Release = LinuxSdioRelease,
600     .moduleName = "HDF_PLATFORM_SDIO",
601 };
602 HDF_INIT(g_sdioDriverEntry);
603