1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "sdhci.h"
17 #include "sdhci_proc.h"
18 
19 #define HDF_LOG_TAG sdhci_adapter
20 
21 #define SDHCI_DMA_MAX_BUFF_SIZE 0x1000
22 #define SDHCI_MAX_BLK_NUM 65535
23 #define SDHCI_DETECET_RETRY 5
24 #define SDHCI_RESET_RETRY_TIMES 100
25 #define SDHCI_OFF_CLK2CARD_ON_DELAY 25
26 #define SDHCI_MAX_HOST_NUM 2
27 #define SDHCI_CLK_CTRL_RETRY_TIMES 20
28 #define SDHCI_PHASE_SCALE_GAP 16
29 #define SDHCI_DIV_MIDDLE 2
30 #define SDHCI_CART_PLUG_STATE (SDHCI_INTERRUPT_CARD_INSERT | SDHCI_INTERRUPT_CARD_REMOVE)
31 #define SDHCI_PLUG_STATE(h) (SdhciReadl(h, PSTATE_R) & SDHCI_CARD_PRESENT)
32 
SdhciDumpregs(struct SdhciHost *host)33 static void SdhciDumpregs(struct SdhciHost *host)
34 {
35     HDF_LOGE(": =========== DUMP (host%u) REGISTER===========", host->hostId);
36     HDF_LOGE(": Sys addr: 0x%08x | Version:  0x%04x",
37         SdhciReadl(host, SDMASA_R), SdhciReadw(host, HOST_VERSION_R));
38     HDF_LOGE(": Blk size: 0x%04x | Blk cnt:  0x%04x",
39         SdhciReadw(host, BLOCKSIZE_R), SdhciReadw(host, BLOCKCOUNT_R));
40     HDF_LOGE(": Argument: 0x%08x | Trn mode: 0x%04x",
41         SdhciReadl(host, ARGUMENT_R), SdhciReadw(host, XFER_MODE_R));
42     HDF_LOGE(": Present:  0x%08x | Host ctl: 0x%08x",
43         SdhciReadl(host, PSTATE_R), SdhciReadb(host, HOST_CTRL1_R));
44     HDF_LOGE(": Power:    0x%08x | Blk gap:  0x%08x",
45         SdhciReadb(host, PWR_CTRL_R), SdhciReadb(host, BLOCK_GAP_CTRL_R));
46     HDF_LOGE(": Wake-up:  0x%08x | Clock:    0x%04x",
47         SdhciReadb(host, WUP_CTRL_R), SdhciReadw(host, CLK_CTRL_R));
48     HDF_LOGE(": Timeout:  0x%08x | Int stat: 0x%08x",
49         SdhciReadb(host, TOUT_CTRL_R), SdhciReadl(host, NORMAL_INT_STAT_R));
50     HDF_LOGE(": Int enab: 0x%08x | Sig enab: 0x%08x",
51         SdhciReadl(host, NORMAL_INT_STAT_EN_R), SdhciReadl(host, NORMAL_INT_SIGNAL_EN_R));
52     HDF_LOGE(": ACMD err: 0x%04x | Slot int: 0x%04x",
53         SdhciReadw(host, AUTO_CMD_STAT_R), SdhciReadw(host, SLOT_INT_STATUS_R));
54     HDF_LOGE(": Caps_1:   0x%08x | Caps_2:   0x%08x",
55         SdhciReadl(host, CAPABILITIES1_R), SdhciReadl(host, CAPABILITIES2_R));
56     HDF_LOGE(": Cmd:      0x%04x | Max curr: 0x%08x | opcode = %d",
57         SdhciReadw(host, CMD_R), SdhciReadl(host, CURR_CAPBILITIES1_R), (SdhciReadw(host, CMD_R) >> 8) & 0x1f);
58     HDF_LOGE(": Resp 1:   0x%08x | Resp 0:   0x%08x",
59         SdhciReadl(host, RESP01_R + 0x4), SdhciReadl(host, RESP01_R));
60     HDF_LOGE(": Resp 3:   0x%08x | Resp 2:   0x%08x",
61         SdhciReadl(host, RESP01_R + 0xC), SdhciReadl(host, RESP01_R + 0x8));
62     HDF_LOGE(": Host ctl2: 0x%04x", SdhciReadw(host, HOST_CTRL2_R));
63     HDF_LOGE(": Emmc ctrl: 0x%04x | Multi cycle 0x%08x",
64         SdhciReadw(host, EMMC_CTRL_R), SdhciReadl(host, MULTI_CYCLE_R));
65     if (host->flags & SDHCI_USE_64BIT_ADMA) {
66         HDF_LOGE(": ADMA Err: 0x%08x\n", SdhciReadl(host, ADMA_ERR_STAT_R));
67         HDF_LOGE(": ADMA Addr(0:31): 0x%08x | ADMA Addr(32:63): 0x%08x",
68             SdhciReadl(host, ADMA_SA_LOW_R), SdhciReadl(host, ADMA_SA_HIGH_R));
69     } else if (host->flags & SDHCI_USE_ADMA) {
70         HDF_LOGE(": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x",
71             SdhciReadl(host, ADMA_ERR_STAT_R), SdhciReadl(host, ADMA_SA_LOW_R));
72     }
73     HDF_LOGE(": ===========================================");
74 }
75 
SdhciDmaCacheClean(void *addr, uint32_t size)76 static void SdhciDmaCacheClean(void *addr, uint32_t size)
77 {
78     addr = (void *)(uintptr_t)DMA_TO_VMM_ADDR((paddr_t)(uintptr_t)addr);
79     uint32_t start = (uintptr_t)addr & ~(CACHE_ALIGNED_SIZE - 1);
80     uint32_t end = (uintptr_t)addr + size;
81 
82     end = ALIGN(end, CACHE_ALIGNED_SIZE);
83     DCacheFlushRange(start, end);
84 }
85 
SdhciDmaCacheInv(void *addr, uint32_t size)86 static void SdhciDmaCacheInv(void *addr, uint32_t size)
87 {
88     addr = (void *)(uintptr_t)DMA_TO_VMM_ADDR((paddr_t)(uintptr_t)addr);
89     uint32_t start = (uintptr_t)addr & ~(CACHE_ALIGNED_SIZE - 1);
90     uint32_t end = (uintptr_t)addr + size;
91 
92     end = ALIGN(end, CACHE_ALIGNED_SIZE);
93     DCacheInvRange(start, end);
94 }
95 
SdhciEnablePlugIrq(struct SdhciHost *host, uint32_t irq)96 static void SdhciEnablePlugIrq(struct SdhciHost *host, uint32_t irq)
97 {
98     SdhciWritel(host, irq, NORMAL_INT_STAT_EN_R);
99     SdhciWritel(host, irq, NORMAL_INT_SIGNAL_EN_R);
100 }
101 
SdhciSetCardDetection(struct SdhciHost *host, bool enable)102 static void SdhciSetCardDetection(struct SdhciHost *host, bool enable)
103 {
104     uint32_t present;
105 
106     if (host->mmc->caps.bits.nonremovable > 0 ||
107         host->quirks.bits.forceSWDetect > 0 ||
108         host->quirks.bits.brokenCardDetection > 0) {
109         return;
110     }
111 
112     if (enable == true) {
113         present = SdhciReadl(host, PSTATE_R) & SDHCI_CARD_PRESENT;
114         host->irqEnable |= (present ? SDHCI_INTERRUPT_CARD_REMOVE : SDHCI_INTERRUPT_CARD_INSERT);
115     } else {
116         host->irqEnable &= (~(SDHCI_INTERRUPT_CARD_REMOVE | SDHCI_INTERRUPT_CARD_INSERT));
117     }
118 }
119 
SdhciEnableCardDetection(struct SdhciHost *host)120 static void SdhciEnableCardDetection(struct SdhciHost *host)
121 {
122     SdhciSetCardDetection(host, true);
123     SdhciWritel(host, host->irqEnable, NORMAL_INT_STAT_EN_R);
124     SdhciWritel(host, host->irqEnable, NORMAL_INT_SIGNAL_EN_R);
125 }
126 
SdhciReset(struct SdhciHost *host, uint32_t mask)127 static void SdhciReset(struct SdhciHost *host, uint32_t mask)
128 {
129     uint32_t i;
130     uint8_t reg;
131 
132     SdhciWriteb(host, mask, SW_RST_R);
133     /* hw clears the bit when it's done */
134     for (i = 0; i < SDHCI_RESET_RETRY_TIMES; i++) {
135         reg = SdhciReadb(host, SW_RST_R);
136         if ((reg & mask) == 0) {
137             return;
138         }
139         OsalMDelay(1);
140     }
141 
142     HDF_LOGE("host%u: Reset 0x%x never completed.", host->hostId, mask);
143     SdhciDumpregs(host);
144 }
145 
SdhciDoReset(struct SdhciHost *host, uint32_t mask)146 static void SdhciDoReset(struct SdhciHost *host, uint32_t mask)
147 {
148     SdhciReset(host, mask);
149 
150     if ((mask & SDHCI_RESET_ALL) > 0) {
151         host->presetEnabled = false;
152         host->clock = 0;
153     }
154 }
155 
SdhciSetTransferMode(struct SdhciHost *host, struct MmcCmd *cmd)156 static void SdhciSetTransferMode(struct SdhciHost *host, struct MmcCmd *cmd)
157 {
158     uint16_t mode;
159 
160     if (cmd->data == NULL) {
161         mode = SdhciReadw(host, XFER_MODE_R);
162         SdhciWritew(host, (mode & (~(SDHCI_TRNS_AUTO_CMD12 | SDHCI_TRNS_AUTO_CMD23))), XFER_MODE_R);
163         return;
164     }
165 
166     mode = SDHCI_TRNS_BLK_CNT_EN;
167     if (cmd->cmdCode == WRITE_MULTIPLE_BLOCK || cmd->cmdCode == READ_MULTIPLE_BLOCK || cmd->data->blockNum > 1) {
168         mode |= SDHCI_TRNS_MULTI;
169         if ((host->mmc->devType == MMC_DEV_SD && (MmcCntlrSdSupportCmd23(host->mmc) == false)) ||
170             (host->mmc->devType == MMC_DEV_EMMC && (MmcCntlrEmmcSupportCmd23(host->mmc) == false))) {
171             mode |= SDHCI_TRNS_AUTO_CMD12;
172         } else {
173             if ((host->flags & SDHCI_AUTO_CMD23)) {
174                 mode |= SDHCI_TRNS_AUTO_CMD23;
175                 SdhciWritel(host, cmd->data->blockNum, SDHCI_ARGUMENT2);
176             } else if ((host->flags & SDHCI_AUTO_CMD12) > 0) {
177                 mode |= SDHCI_TRNS_AUTO_CMD12;
178             }
179         }
180     }
181 
182     if ((cmd->data->dataFlags & DATA_READ) > 0) {
183         mode |= SDHCI_TRNS_READ;
184     }
185     if ((host->flags & SDHCI_REQ_USE_DMA) > 0) {
186         mode |= SDHCI_TRNS_DMA;
187     }
188     SdhciWritew(host, mode, XFER_MODE_R);
189 }
190 
SdhciTaskletFinish(struct SdhciHost *host)191 static void SdhciTaskletFinish(struct SdhciHost *host)
192 {
193     struct MmcCmd *cmd = host->cmd;
194 
195     if (!(host->flags & SDHCI_DEVICE_DEAD) &&
196         ((cmd->returnError != 0) || (cmd->data != NULL && cmd->data->returnError != 0))) {
197         SdhciDoReset(host, SDHCI_RESET_CMD);
198         SdhciDoReset(host, SDHCI_RESET_DATA);
199     }
200 
201     host->cmd = NULL;
202     (void)SDHCI_EVENT_SIGNAL(&host->sdhciEvent, SDHCI_PEND_REQUEST_DONE);
203 }
204 
SdhciGenerateCmdFlag(struct MmcCmd *cmd)205 static uint32_t SdhciGenerateCmdFlag(struct MmcCmd *cmd)
206 {
207     uint32_t flags;
208 
209     if ((cmd->respType & RESP_PRESENT) == 0) {
210         flags = SDHCI_CMD_NONE_RESP;
211     } else if ((cmd->respType & RESP_136) > 0) {
212         flags = SDHCI_CMD_LONG_RESP;
213     } else if ((cmd->respType & RESP_BUSY) > 0) {
214         flags = SDHCI_CMD_SHORT_RESP_BUSY;
215     } else {
216         flags = SDHCI_CMD_SHORT_RESP;
217     }
218 
219     if ((cmd->respType & RESP_CRC) > 0) {
220         flags |= SDHCI_CMD_CRC_CHECK_ENABLE;
221     }
222     if ((cmd->respType & RESP_CMDCODE) > 0) {
223         flags |= SDHCI_CMD_INDEX_CHECK_ENABLE;
224     }
225 
226     /* CMD19 is special in that the Data Present Select should be set */
227     if (cmd->data != NULL || cmd->cmdCode == SD_CMD_SEND_TUNING_BLOCK || cmd->cmdCode == SEND_TUNING_BLOCK_HS200) {
228         flags |= SDHCI_CMD_DATA_TX;
229     }
230 
231     return flags;
232 }
233 
SdhciSetDmaConfig(struct SdhciHost *host)234 static void SdhciSetDmaConfig(struct SdhciHost *host)
235 {
236     uint8_t ctrl;
237 
238     if (host->version < SDHCI_HOST_SPEC_200) {
239         return;
240     }
241 
242     ctrl = SdhciReadb(host, HOST_CTRL1_R);
243     ctrl &= ~SDHCI_CTRL_DMA_ENABLE_MASK;
244     if ((host->flags & SDHCI_REQ_USE_DMA) && (host->flags & SDHCI_USE_ADMA)) {
245         if (host->flags & SDHCI_USE_64BIT_ADMA) {
246             ctrl |= SDHCI_CTRL_ADMA64_ENABLE;
247         } else {
248             ctrl |= SDHCI_CTRL_ADMA32_ENABLE;
249         }
250     } else {
251         ctrl |= SDHCI_CTRL_SDMA_ENABLE;
252     }
253     SdhciWriteb(host, ctrl, HOST_CTRL1_R);
254 }
255 
SdhciSetTransferIrqs(struct SdhciHost *host)256 static void SdhciSetTransferIrqs(struct SdhciHost *host)
257 {
258     uint32_t pioIrqs = SDHCI_INTERRUPT_DATA_AVAIL | SDHCI_INTERRUPT_SPACE_AVAIL;
259     uint32_t dmaIrqs = SDHCI_INTERRUPT_DMA_END | SDHCI_INTERRUPT_ADMA_ERROR;
260 
261     if (host->flags & SDHCI_REQ_USE_DMA) {
262         host->irqEnable = (host->irqEnable & ~pioIrqs) | dmaIrqs;
263     } else {
264         host->irqEnable = (host->irqEnable & ~dmaIrqs) | pioIrqs;
265     }
266     SdhciEnablePlugIrq(host, host->irqEnable);
267 }
268 
SdhciSetBlkSizeReg(struct SdhciHost *host, uint32_t blksz, uint32_t sdmaBoundary)269 static void SdhciSetBlkSizeReg(struct SdhciHost *host, uint32_t blksz, uint32_t sdmaBoundary)
270 {
271     if (host->flags & SDHCI_USE_ADMA) {
272         SdhciWritel(host, SDHCI_MAKE_BLKSZ(7, blksz), BLOCKSIZE_R);
273     } else {
274         SdhciWritel(host, SDHCI_MAKE_BLKSZ(sdmaBoundary, blksz), BLOCKSIZE_R);
275     }
276 }
277 
SdhciAdmaConfig(struct SdhciHost *host)278 static void SdhciAdmaConfig(struct SdhciHost *host)
279 {
280     SdhciWritel(host, 0, (uintptr_t)ADMA_SA_HIGH_R);
281     SdhciWritel(host, VMM_TO_DMA_ADDR((uintptr_t)host->admaDesc), (uintptr_t)ADMA_SA_LOW_R);
282 }
283 
SdhciSetAdmaDesc(struct SdhciHost *host, char *desc, dma_addr_t addr, uint16_t len, uint16_t cmd)284 static void SdhciSetAdmaDesc(struct SdhciHost *host, char *desc, dma_addr_t addr, uint16_t len, uint16_t cmd)
285 {
286     uint16_t *cmdlen = (uint16_t *)desc;
287 
288     cmdlen[0] = (cmd);
289     cmdlen[1] = (len);
290 
291     if (host->flags & SDHCI_USE_64BIT_ADMA) {
292         unsigned long *dataddr = (unsigned long*)(desc + 4);
293         dataddr[0] = (addr);
294     } else {
295         uint32_t *dataddr = (uint32_t *)(desc + 4);
296         dataddr[0] = (addr);
297     }
298 }
299 
SdhciAdmaMarkEnd(void *desc)300 static void SdhciAdmaMarkEnd(void *desc)
301 {
302     uint16_t *d = (uint16_t *)desc;
303 
304     d[0] |= ADMA2_END;
305 }
306 
SdhciAdmaTablePre(struct SdhciHost *host, struct MmcData *data)307 static int32_t SdhciAdmaTablePre(struct SdhciHost *host, struct MmcData *data)
308 {
309     char *admaDesc = NULL;
310     dma_addr_t addr;
311     uint32_t len, i;
312     uint32_t dmaDir = DMA_TO_DEVICE;
313 
314     if (data->dataFlags & DATA_READ) {
315         dmaDir = DMA_FROM_DEVICE;
316     }
317 
318     admaDesc = host->admaDesc;
319     (void)memset_s(admaDesc, ALIGN(host->admaDescSize, CACHE_ALIGNED_SIZE),
320         0, ALIGN(host->admaDescSize, CACHE_ALIGNED_SIZE));
321 
322     for (i = 0; i < host->dmaSgCount; i++) {
323         addr = SDHCI_SG_DMA_ADDRESS(&host->sg[i]);
324         len = SDHCI_SG_DMA_LEN(&host->sg[i]);
325         if (dmaDir == DMA_TO_DEVICE) {
326             SdhciDmaCacheClean((void*)addr, len);
327         } else {
328             SdhciDmaCacheInv((void*)addr, len);
329         }
330 
331         while (len > 0) {
332             if (len > SDHCI_DMA_MAX_BUFF_SIZE) {
333                 SdhciSetAdmaDesc(host, admaDesc, addr, SDHCI_DMA_MAX_BUFF_SIZE, 0x21);
334                 len -= SDHCI_DMA_MAX_BUFF_SIZE;
335                 addr += SDHCI_DMA_MAX_BUFF_SIZE;
336             } else {
337                 SdhciSetAdmaDesc(host, admaDesc, addr, len, 0x21);
338                 len = 0;
339             }
340             admaDesc += host->admaDescLineSize;
341         }
342 
343         if ((uint32_t)(admaDesc - host->admaDesc) > host->admaDescSize) {
344             HDF_LOGE("check wrong!");
345         }
346     }
347 
348     if (host->quirks.bits.noEndattrInNopdesc) {
349         /* Mark the last descriptor as the terminating descriptor */
350         if (admaDesc != host->admaDesc) {
351             admaDesc -= host->admaDescLineSize;
352             SdhciAdmaMarkEnd(admaDesc);
353         }
354     } else {
355         SdhciSetAdmaDesc(host, admaDesc, 0, 0, 0x3);
356     }
357     SdhciDmaCacheClean((void*)VMM_TO_DMA_ADDR((uintptr_t)host->admaDesc),
358         ALIGN(host->admaDescSize, CACHE_ALIGNED_SIZE));
359 
360     return 0;
361 }
362 
SdhciPrepareData(struct SdhciHost *host)363 static void SdhciPrepareData(struct SdhciHost *host)
364 {
365     struct MmcCmd *cmd = host->cmd;
366     struct MmcData *data = cmd->data;
367     int32_t retval;
368 
369     /* set timeout value , use default value. */
370     if (data != NULL || (cmd->respType & RESP_BUSY) > 0) {
371         SdhciWriteb(host, SDHCI_DEFINE_TIMEOUT, TOUT_CTRL_R);
372     }
373     if (data == NULL) {
374         return;
375     }
376 
377     if (host->flags & (SDHCI_USE_ADMA | SDHCI_USE_SDMA)) {
378         host->flags |= SDHCI_REQ_USE_DMA;
379     }
380 
381     if (host->flags & SDHCI_REQ_USE_DMA) {
382         if (host->flags & SDHCI_USE_ADMA) {
383             /* ADMA config */
384             retval = SdhciAdmaTablePre(host, data);
385             if (retval) {
386                 host->flags &= ~SDHCI_REQ_USE_DMA;
387             } else {
388                 SdhciWritel(host, 0, SDHCI_DMA_ADDRESS);
389                 SdhciAdmaConfig(host);
390             }
391         } else {
392             /* SDMA config */
393             SdhciWritel(host, SDHCI_SG_DMA_ADDRESS(&host->sg[0]), SDHCI_DMA_ADDRESS);
394         }
395     }
396 
397     SdhciSetDmaConfig(host);
398     SdhciSetTransferIrqs(host);
399     SdhciSetBlkSizeReg(host, data->blockSize, SDHCI_DEFAULT_BOUNDARY_ARG);
400     SdhciWritew(host, data->blockNum, BLOCKCOUNT_R);
401 }
402 
SdhciExecCmd(struct SdhciHost *host, struct MmcCmd *cmd)403 static void SdhciExecCmd(struct SdhciHost *host, struct MmcCmd *cmd)
404 {
405     uint32_t mask, flags;
406     uint32_t timeout = 10; /* 10ms */
407 
408     mask = SDHCI_CMD_INVALID;
409     if ((cmd->data != NULL) || ((cmd->respType & RESP_BUSY) > 0)) {
410         mask |= SDHCI_DATA_INVALID;
411     }
412 
413     if ((cmd->data != NULL) && (cmd->data->sendStopCmd == true)) {
414         mask &= ~SDHCI_DATA_INVALID;
415     }
416 
417     /* wait host ready */
418     while (SdhciReadl(host, PSTATE_R) & mask) {
419         if (timeout == 0) {
420             HDF_LOGE("exec cmd %u timeout!\n", cmd->cmdCode);
421             SdhciDumpregs(host);
422             cmd->returnError = HDF_ERR_IO;
423             SdhciTaskletFinish(host);
424             return;
425         }
426         timeout--;
427         OsalMDelay(1);
428     }
429 
430     host->cmd = cmd;
431     SdhciPrepareData(host);
432     SdhciWritel(host, cmd->argument, ARGUMENT_R);
433     SdhciSetTransferMode(host, cmd);
434 
435     if ((cmd->respType & RESP_136) && (cmd->respType & RESP_BUSY)) {
436         HDF_LOGE("host%u: Unsupported response type!", host->hostId);
437         cmd->returnError = HDF_FAILURE;
438         SdhciTaskletFinish(host);
439         return;
440     }
441 
442     flags = SdhciGenerateCmdFlag(cmd);
443     SdhciWritew(host, SDHCI_GEN_CMD(cmd->cmdCode, flags), CMD_R);
444 }
445 
SdhciCardPlugged(struct MmcCntlr *cntlr)446 static bool SdhciCardPlugged(struct MmcCntlr *cntlr)
447 {
448     struct SdhciHost *host = NULL;
449 
450     if ((cntlr == NULL) || (cntlr->priv == NULL)) {
451         return false;
452     }
453 
454     if (cntlr->devType == MMC_DEV_SDIO || cntlr->devType == MMC_DEV_EMMC) {
455         return true;
456     }
457 
458     host = (struct SdhciHost *)cntlr->priv;
459     if (host->quirks.bits.brokenCardDetection > 0 ||
460         host->quirks.bits.forceSWDetect > 0) {
461         return true;
462     }
463     return ((SdhciReadl(host, PSTATE_R) & SDHCI_CARD_PRESENT) > 0 ? true : false);
464 }
465 
SdhciFillDmaSg(struct SdhciHost *host)466 static int32_t SdhciFillDmaSg(struct SdhciHost *host)
467 {
468     struct MmcData *data = host->cmd->data;
469     uint32_t len = data->blockNum * data->blockSize;
470     int32_t ret;
471 
472     if (len == 0) {
473         return HDF_ERR_INVALID_PARAM;
474     }
475 
476     if (data->scatter != NULL && data->dataBuffer == NULL) {
477         host->sg = data->scatter;
478         host->dmaSgCount = data->scatterLen;
479         return HDF_SUCCESS;
480     }
481     if (data->dataBuffer == NULL) {
482         return HDF_ERR_INVALID_PARAM;
483     }
484 
485     host->alignedBuff = (uint8_t *)OsalMemAllocAlign(CACHE_ALIGNED_SIZE, ALIGN(len, CACHE_ALIGNED_SIZE));
486     if (host->alignedBuff == NULL) {
487         HDF_LOGE("out of memory.");
488         return HDF_ERR_MALLOC_FAIL;
489     }
490 
491     ret = memcpy_s(host->alignedBuff, len, data->dataBuffer, len);
492     if (ret != EOK) {
493         HDF_LOGE("memcpy_s fail ret = %d.", ret);
494         free(host->alignedBuff);
495         host->alignedBuff = NULL;
496         return HDF_FAILURE;
497     }
498     host->buffLen = len;
499     sg_init_one(&host->dmaSg, (const void *)host->alignedBuff, len);
500     host->dmaSgCount = 1;
501     host->sg = &host->dmaSg;
502     return HDF_SUCCESS;
503 }
504 
SdhciClearDmaSg(struct SdhciHost *host, struct MmcData *data)505 static void SdhciClearDmaSg(struct SdhciHost *host, struct MmcData *data)
506 {
507     uint32_t len;
508 
509     if (data == NULL) {
510         return;
511     }
512 
513     len = data->blockNum * data->blockSize;
514     if (host->alignedBuff != NULL && data->dataBuffer != NULL && len > 0 && host->buffLen > 0) {
515         if ((data->dataFlags & DATA_READ) > 0) {
516             (void)memcpy_s(data->dataBuffer, len, host->alignedBuff, host->buffLen);
517         }
518     }
519     if (host->alignedBuff != NULL) {
520         OsalMemFree(host->alignedBuff);
521         host->alignedBuff = NULL;
522     }
523     host->buffLen = 0;
524     host->dmaSgCount = 0;
525     host->sg = NULL;
526 }
527 
SdhciDataSync(struct SdhciHost *host, struct MmcData *data)528 static void SdhciDataSync(struct SdhciHost *host, struct MmcData *data)
529 {
530     uint32_t sgPhyAddr, sgLength, i;
531 
532     if ((data->dataFlags & DATA_READ) > 0) {
533         for (i = 0; i < host->dmaSgCount; i++) {
534             sgLength = SDHCI_SG_DMA_LEN(&host->sg[i]);
535             sgPhyAddr = SDHCI_SG_DMA_ADDRESS(&host->sg[i]);
536             SdhciDmaCacheInv((void *)(uintptr_t)sgPhyAddr, sgLength);
537         }
538     }
539 }
540 
SdhciDoRequest(struct MmcCntlr *cntlr, struct MmcCmd *cmd)541 static int32_t SdhciDoRequest(struct MmcCntlr *cntlr, struct MmcCmd *cmd)
542 {
543     struct SdhciHost *host = (struct SdhciHost *)cntlr->priv;
544     int32_t ret;
545     unsigned long flags = 0;
546     uint32_t timeout = SDHCI_CMD_DATA_REQ_TIMEOUT;
547 
548     (void)OsalMutexLock(&host->mutex);
549 
550     host->cmd = cmd;
551     if (cmd->data != NULL) {
552         ret = SdhciFillDmaSg(host);
553         if (ret != HDF_SUCCESS) {
554             goto _END;
555         }
556     }
557 
558     if (SdhciCardPlugged(host->mmc) == false || (host->flags & SDHCI_DEVICE_DEAD) > 0) {
559         cmd->returnError = HDF_ERR_IO;
560         HDF_LOGE("card is not present!");
561         SdhciEnableCardDetection(host);
562         ret = HDF_ERR_IO;
563         goto _END;
564     } else {
565         SdhciExecCmd(host, cmd);
566     }
567 
568     SDHCI_IRQ_LOCK(&flags);
569     host->waitForEvent = true;
570     SDHCI_IRQ_UNLOCK(flags);
571 
572     if (cmd->data == NULL && host->quirks.bits.forceSWDetect > 0) {
573         timeout = SDHCI_CMD_REQ_TIMEOUT;
574     }
575 
576     ret = SDHCI_EVENT_WAIT(&host->sdhciEvent, SDHCI_PEND_REQUEST_DONE | SDHCI_PEND_ACCIDENT, timeout);
577 
578     SDHCI_IRQ_LOCK(&flags);
579     host->waitForEvent = false;
580     SDHCI_IRQ_UNLOCK(flags);
581 
582     if (ret != SDHCI_PEND_REQUEST_DONE) {
583         SdhciDumpregs(host);
584         cmd->returnError = HDF_ERR_TIMEOUT;
585         if (ret == SDHCI_PEND_ACCIDENT) {
586             cmd->returnError = HDF_ERR_IO;
587         }
588         SdhciDoReset(host, SDHCI_RESET_CMD);
589         SdhciDoReset(host, SDHCI_RESET_DATA);
590         host->cmd = NULL;
591     } else if (cmd->data != NULL) {
592         SdhciDataSync(host, cmd->data);
593     }
594     ret = HDF_SUCCESS;
595 _END:
596     SdhciClearDmaSg(host, cmd->data);
597     (void)OsalMutexUnlock(&host->mutex);
598     return ret;
599 }
600 
SdhciResetDll(struct SdhciHost *host)601 void SdhciResetDll(struct SdhciHost *host)
602 {
603     uint32_t reg, value;
604     uint32_t cfgArray[] = { PERI_CRG125, PERI_CRG139 };
605 
606     if (host->hostId >= SDHCI_MAX_HOST_NUM) {
607         return;
608     }
609 
610     reg = cfgArray[host->hostId];
611     value = OSAL_READL((uintptr_t)reg);
612     value |= SDHCI_EMMC_DLL_RST;
613     OSAL_WRITEL(value, (uintptr_t)reg);
614 }
615 
SdhciSelectClock(struct SdhciHost *host, uint32_t clock)616 static uint32_t SdhciSelectClock(struct SdhciHost *host, uint32_t clock)
617 {
618     uint32_t reg, realClock, value;
619     uint32_t temp = 0;
620     uint32_t cfgArray[] = { PERI_CRG125, PERI_CRG139 };
621 
622     if (host->hostId >= SDHCI_MAX_HOST_NUM) {
623         HDF_LOGE("host id=%u is not supported!", host->hostId);
624         return 0;
625     }
626 
627     if (host->hostId == 1 && (clock > SDHCI_MMC_FREQ_50M)) {
628         HDF_LOGE("host%u doesn't support freq %u!", host->hostId, clock);
629         return 0;
630     }
631 
632     if (clock >= SDHCI_MMC_FREQ_150M) {
633         temp |= SDHCI_CLK_SEL_150M;
634         realClock = SDHCI_MMC_FREQ_150M;
635     } else if (clock >= SDHCI_MMC_FREQ_112P5M) {
636         temp |= SDHCI_CLK_SEL_112P5M;
637         realClock = SDHCI_MMC_FREQ_112P5M;
638     } else if (clock >= SDHCI_MMC_FREQ_90M) {
639         temp |= SDHCI_CLK_SEL_90M;
640         realClock = SDHCI_MMC_FREQ_90M;
641     } else if (clock >= SDHCI_MMC_FREQ_50M) {
642         temp |= SDHCI_CLK_SEL_50M;
643         realClock = SDHCI_MMC_FREQ_50M;
644     } else if (clock >= SDHCI_MMC_FREQ_25M) {
645         temp |= SDHCI_CLK_SEL_25M;
646         realClock = SDHCI_MMC_FREQ_25M;
647     } else if (clock >= SDHCI_MMC_FREQ_400K) {
648         temp |= SDHCI_CLK_SEL_400K;
649         realClock = SDHCI_MMC_FREQ_400K;
650     } else if (clock >= SDHCI_MMC_FREQ_100K) {
651         temp = SDHCI_CLK_SEL_100K;
652         realClock = SDHCI_MMC_FREQ_100K;
653     } else {
654         temp = SDHCI_CLK_SEL_100K;
655         realClock = 0;
656     }
657 
658     reg = cfgArray[host->hostId];
659     value = OSAL_READL((uintptr_t)reg);
660     value &= ~(SDHCI_MMC_FREQ_MASK << SDHCI_MMC_FREQ_SHIFT);
661     value |= ((temp & SDHCI_MMC_FREQ_MASK) << SDHCI_MMC_FREQ_SHIFT);
662     value |= SDHCI_CKEN;
663     OSAL_WRITEL(value, (uintptr_t)reg);
664 
665     return realClock;
666 }
667 
SdhciSetDrvPhase(uint32_t id, uint32_t phase)668 static void SdhciSetDrvPhase(uint32_t id, uint32_t phase)
669 {
670     uint32_t value;
671     uint32_t drv[] = { PERI_CRG127, PERI_CRG136 };
672 
673     if (id >= SDHCI_MAX_HOST_NUM) {
674         return;
675     }
676 
677     value = OSAL_READL(drv[id]);
678     value &= (~SDHCI_DRV_CLK_PHASE_MASK);
679     value |= (phase << SDHCI_DRV_CLK_PHASE_SHFT);
680     OSAL_WRITEL(value, drv[id]);
681 }
682 
SdhciEnableSample(struct SdhciHost *host)683 static void SdhciEnableSample(struct SdhciHost *host)
684 {
685     uint32_t val;
686 
687     val = SdhciReadl(host, AT_CTRL_R);
688     val |= SDHCI_SW_TUNING_EN;
689     SdhciWritel(host, val, AT_CTRL_R);
690 }
691 
SdhciSetSampPhase(struct SdhciHost *host, uint32_t phase)692 static void SdhciSetSampPhase(struct SdhciHost *host, uint32_t phase)
693 {
694     uint32_t val;
695     val = SdhciReadl(host, AT_STAT_R);
696     val = SdhciReadl(host, AT_STAT_R);
697     val &= ~SDHCI_CENTER_PH_CODE_MASK;
698     val |= phase;
699     SdhciWritel(host, val, AT_STAT_R);
700 }
701 
SdhciSetIo(uint32_t offset, uint32_t val)702 static void SdhciSetIo(uint32_t offset, uint32_t val)
703 {
704     uint32_t reg;
705 
706     reg = OSAL_READL(offset);
707     reg &= ~IO_DRV_MASK;
708     reg |= val & IO_DRV_MASK;
709     OSAL_WRITEL(reg, offset);
710 }
711 
SdhciSetIodriver(uint32_t offset, uint32_t pull, uint32_t sr, uint32_t drv)712 static void SdhciSetIodriver(uint32_t offset, uint32_t pull, uint32_t sr, uint32_t drv)
713 {
714     SdhciSetIo(offset, pull | (sr ? IO_CFG_SR : 0) | IO_DRV_STR_SEL(drv));
715 }
716 
SdhciSetSdiodriver(struct SdhciHost *host)717 static void SdhciSetSdiodriver(struct SdhciHost *host)
718 {
719     uint32_t i, count;
720     uint32_t dataRegs[] = { REG_CTRL_SDIO_DATA0, REG_CTRL_SDIO_DATA1, REG_CTRL_SDIO_DATA2, REG_CTRL_SDIO_DATA3 };
721 
722     count = sizeof(dataRegs) / sizeof(dataRegs[0]);
723     if (host->mmc->caps.bits.cap4Bit == 0) {
724         /* only 1 pin can be initialized, because other pins are reserved to configured as other functions. */
725         count = 1;
726     }
727     SdhciSetIodriver(REG_CTRL_SDIO_CLK, IO_CFG_PULL_DOWN, IO_CFG_SR, IO_DRV_SDIO_CLK);
728     SdhciSetIodriver(REG_CTRL_SDIO_CMD, IO_CFG_PULL_UP, 0, IO_DRV_SDIO_CMD);
729     for (i = 0; i < count; i++) {
730         SdhciSetIodriver(dataRegs[i], IO_CFG_PULL_UP, 0, IO_DRV_SDIO_DATA);
731     }
732 }
733 
SdhciSetSdDriver(struct SdhciHost *host, enum MmcBusTiming timing)734 static void SdhciSetSdDriver(struct SdhciHost *host, enum MmcBusTiming timing)
735 {
736     uint32_t i, count;
737     uint32_t dataRegs[] = { REG_CTRL_SD_DATA0, REG_CTRL_SD_DATA1, REG_CTRL_SD_DATA2, REG_CTRL_SD_DATA3 };
738 
739     count = sizeof(dataRegs) / sizeof(dataRegs[0]);
740     if (host->mmc->caps.bits.cap4Bit == 0) {
741         /* only 1-pin GPIO can be initialized, because other pins are reserved to configured as other functions. */
742         count = 1;
743     }
744 
745     switch (timing) {
746         case BUS_TIMING_SD_HS:
747             SdhciSetIodriver(REG_CTRL_SD_CLK, IO_CFG_PULL_DOWN, IO_CFG_SR, IO_DRV_SD_SDHS_CLK);
748             SdhciSetIodriver(REG_CTRL_SD_CMD, IO_CFG_PULL_UP, IO_CFG_SR, IO_DRV_SD_SDHS_CMD);
749             for (i = 0; i < count; i++) {
750                 SdhciSetIodriver(dataRegs[i], IO_CFG_PULL_UP, IO_CFG_SR, IO_DRV_SD_SDHS_DATA);
751             }
752             break;
753         default:
754             SdhciSetIodriver(REG_CTRL_SD_CLK, IO_CFG_PULL_DOWN, IO_CFG_SR, IO_DRV_SD_OTHER_CLK);
755             SdhciSetIodriver(REG_CTRL_SD_CMD, IO_CFG_PULL_UP, IO_CFG_SR, IO_DRV_SD_OTHER_CMD);
756             for (i = 0; i < count; i++) {
757                 SdhciSetIodriver(dataRegs[i], IO_CFG_PULL_UP, IO_CFG_SR, IO_DRV_SD_OTHER_DATA);
758             }
759             break;
760     }
761 }
762 
SdhciSetEmmcCtrl(struct SdhciHost *host)763 static void SdhciSetEmmcCtrl(struct SdhciHost *host)
764 {
765     unsigned int val;
766 
767     val = SdhciReadl(host, EMMC_CTRL_R);
768     val |= SDHCI_EMMC_CTRL_EMMC;
769     SdhciWritel(host, val, EMMC_CTRL_R);
770 }
771 
SdhciSetEmmcDriver(struct SdhciHost *host, enum MmcBusTiming timing)772 static void SdhciSetEmmcDriver(struct SdhciHost *host, enum MmcBusTiming timing)
773 {
774     uint32_t i, count;
775     uint32_t dataRegs[] = { REG_CTRL_EMMC_DATA0, REG_CTRL_EMMC_DATA1, REG_CTRL_EMMC_DATA2, REG_CTRL_EMMC_DATA3 };
776 
777     count = sizeof(dataRegs) / sizeof(dataRegs[0]);
778     switch (timing) {
779         case BUS_TIMING_MMC_HS400:
780             SdhciSetEmmcCtrl(host);
781             SdhciSetIodriver(REG_CTRL_EMMC_CLK, IO_CFG_PULL_DOWN, 0, IO_DRV_EMMC_HS400_CLK);
782             SdhciSetIodriver(REG_CTRL_EMMC_CMD, IO_CFG_PULL_UP, 0, IO_DRV_EMMC_HS400_CMD);
783             for (i = 0; i < count; i++) {
784                 SdhciSetIodriver(dataRegs[i], IO_CFG_PULL_UP, 0, IO_DRV_EMMC_HS400_DATA);
785             }
786             SdhciSetIodriver(REG_CTRL_EMMC_DS, IO_CFG_PULL_DOWN, IO_CFG_SR, IO_DRV_EMMC_HS400_DS);
787             SdhciSetIodriver(REG_CTRL_EMMC_RST, IO_CFG_PULL_UP, IO_CFG_SR, IO_DRV_EMMC_HS400_RST);
788             break;
789         case BUS_TIMING_MMC_HS200:
790             SdhciSetEmmcCtrl(host);
791             SdhciSetIodriver(REG_CTRL_EMMC_CLK, IO_CFG_PULL_DOWN, 0, IO_DRV_EMMC_HS200_CLK);
792             SdhciSetIodriver(REG_CTRL_EMMC_CMD, IO_CFG_PULL_UP, IO_CFG_SR, IO_DRV_EMMC_HS200_CMD);
793             for (i = 0; i < count; i++) {
794                 SdhciSetIodriver(dataRegs[i], IO_CFG_PULL_UP, IO_CFG_SR, IO_DRV_EMMC_HS200_DATA);
795             }
796             SdhciSetIodriver(REG_CTRL_EMMC_RST, IO_CFG_PULL_UP, IO_CFG_SR, IO_DRV_EMMC_HS200_RST);
797             break;
798         case BUS_TIMING_MMC_HS:
799             SdhciSetEmmcCtrl(host);
800             SdhciSetIodriver(REG_CTRL_EMMC_CLK, IO_CFG_PULL_DOWN, IO_CFG_SR, IO_DRV_EMMC_HS_CLK);
801             SdhciSetIodriver(REG_CTRL_EMMC_CMD, IO_CFG_PULL_UP, IO_CFG_SR, IO_DRV_EMMC_HS_CMD);
802             for (i = 0; i < count; i++) {
803                 SdhciSetIodriver(dataRegs[i], IO_CFG_PULL_UP, IO_CFG_SR, IO_DRV_EMMC_HS_DATA);
804             }
805             SdhciSetIodriver(REG_CTRL_EMMC_RST, IO_CFG_PULL_UP, IO_CFG_SR, IO_DRV_EMMC_HS_RST);
806             break;
807         default:
808             SdhciSetIodriver(REG_CTRL_EMMC_CLK, IO_CFG_PULL_DOWN, IO_CFG_SR, IO_DRV_EMMC_OTHER_CLK);
809             SdhciSetIodriver(REG_CTRL_EMMC_CMD, IO_CFG_PULL_UP, IO_CFG_SR, IO_DRV_EMMC_OTHER_CMD);
810             for (i = 0; i < count; i++) {
811                 SdhciSetIodriver(dataRegs[i], IO_CFG_PULL_UP, IO_CFG_SR, IO_DRV_EMMC_OTHER_DATA);
812             }
813             SdhciSetIodriver(REG_CTRL_EMMC_RST, IO_CFG_PULL_UP, IO_CFG_SR, IO_DRV_EMMC_OTHER_RST);
814             break;
815     }
816 }
817 
SdhciSetMmcIoDriver(struct SdhciHost *host, enum MmcBusTiming timing)818 static void SdhciSetMmcIoDriver(struct SdhciHost *host, enum MmcBusTiming timing)
819 {
820     uint32_t val;
821 
822     if (host->hostId == 0) {
823         /* mmc0: eMMC or SD card */
824         val = OSAL_READL(REG_CTRL_EMMC_CLK) & IO_MUX_MASK;
825         if (val == IO_MUX_SHIFT(IO_MUX_CLK_TYPE_EMMC)) {
826             SdhciSetEmmcDriver(host, timing);
827         }
828         val = OSAL_READL(REG_CTRL_SD_CLK) & IO_MUX_MASK;
829         if (val == IO_MUX_SHIFT(IO_MUX_CLK_TYPE_SD)) {
830             SdhciSetSdDriver(host, timing);
831         }
832     } else if (host->hostId == 1) {
833         /* mmc1: SDIO */
834         SdhciSetSdiodriver(host);
835     }
836 }
837 
SdhciSetPhase(struct SdhciHost *host)838 static void SdhciSetPhase(struct SdhciHost *host)
839 {
840     uint32_t drvPhase, phase;
841     enum MmcBusTiming timing;
842 
843     if (host->mmc->curDev == NULL) {
844         return;
845     }
846     timing = host->mmc->curDev->workPara.timing;
847 
848     if (host->hostId == 0) {
849         /* eMMC or SD card */
850         if (timing == BUS_TIMING_MMC_HS400) {
851             drvPhase = SDHCI_PHASE_112P5_DEGREE;
852             phase = host->tuningPhase;
853         } else if (timing == BUS_TIMING_MMC_HS200) {
854             drvPhase = SDHCI_PHASE_258P75_DEGREE;
855             phase = host->tuningPhase;
856         } else if (timing == BUS_TIMING_MMC_HS) {
857             drvPhase = SDHCI_PHASE_180_DEGREE;
858             phase = SDHCI_SAMPLE_PHASE;
859         } else if (timing == BUS_TIMING_SD_HS) {
860             drvPhase = SDHCI_PHASE_225_DEGREE;
861             phase = SDHCI_SAMPLE_PHASE;
862         } else if (timing == BUS_TIMING_MMC_DS) {
863             drvPhase = SDHCI_PHASE_180_DEGREE;
864             phase = 0;
865         } else {
866             drvPhase = SDHCI_PHASE_225_DEGREE;
867             phase = SDHCI_SAMPLE_PHASE;
868         }
869     } else {
870         /* SDIO device */
871         if ((timing == BUS_TIMING_SD_HS) ||
872             (timing == BUS_TIMING_UHS_SDR25)) {
873             drvPhase = SDHCI_PHASE_180_DEGREE;
874             phase = SDHCI_SAMPLE_PHASE;
875         } else {
876             /* UHS_SDR12 */
877             drvPhase = SDHCI_PHASE_180_DEGREE;
878             phase = 0;
879         }
880     }
881 
882     SdhciSetDrvPhase(host->hostId, drvPhase);
883     SdhciEnableSample(host);
884     SdhciSetSampPhase(host, phase);
885     SdhciSetMmcIoDriver(host, timing);
886 }
887 
SdhciSetClock(struct MmcCntlr *cntlr, uint32_t clock)888 static int32_t SdhciSetClock(struct MmcCntlr *cntlr, uint32_t clock)
889 {
890     struct SdhciHost *host = (struct SdhciHost *)cntlr->priv;
891     uint16_t clk;
892     uint32_t i, ret;
893 
894     /* turn off clk2card_on */
895     clk = SdhciReadw(host, CLK_CTRL_R);
896     clk &= ~(SDHCI_CLK_CTRL_CLK_EN);
897     SdhciWritew(host, clk, CLK_CTRL_R);
898     OsalUDelay(SDHCI_OFF_CLK2CARD_ON_DELAY);
899 
900     /* turn off card_clk_en */
901     clk &= ~(SDHCI_CLK_CTRL_INT_CLK_EN | SDHCI_CLK_CTRL_PLL_EN);
902     SdhciWritew(host, clk, CLK_CTRL_R);
903 
904     if (clock == 0) {
905         return HDF_FAILURE;
906     }
907     if (clock >= host->maxClk) {
908         clock = host->maxClk;
909     }
910 
911     SdhciResetDll(host);
912     SdhciSetPhase(host);
913 
914     ret = SdhciSelectClock(host, clock);
915     if (ret == 0) {
916         HDF_LOGE("Select clock fail!");
917         return HDF_FAILURE;
918     }
919     host->clock = ret;
920     if (cntlr->caps.bits.nonremovable == 0) {
921         SdhciResetDll(host);
922     }
923 
924     /* turn on card_clk_en */
925     clk |= SDHCI_CLK_CTRL_INT_CLK_EN | SDHCI_CLK_CTRL_PLL_EN;
926     SdhciWritew(host, clk, CLK_CTRL_R);
927     for (i = 0; i < SDHCI_CLK_CTRL_RETRY_TIMES; i++) {
928         clk = SdhciReadw(host, CLK_CTRL_R);
929         if ((clk & SDHCI_CLK_CTRL_INT_STABLE) > 0) {
930             break;
931         }
932         OsalMDelay(1);
933     }
934     if (i == SDHCI_CLK_CTRL_RETRY_TIMES) {
935         HDF_LOGE("Internal clock never stabilized.");
936         return HDF_ERR_TIMEOUT;
937     }
938 
939     SdhciResetDll(host);
940     /* turn on clk2card_on */
941     clk |= SDHCI_CLK_CTRL_CLK_EN;
942     SdhciWritew(host, clk, CLK_CTRL_R);
943     return HDF_SUCCESS;
944 }
945 
SdhciInit(struct SdhciHost *host, bool resetAll)946 static void SdhciInit(struct SdhciHost *host, bool resetAll)
947 {
948     uint32_t reg;
949     if (resetAll == false) {
950         SdhciDoReset(host, (SDHCI_RESET_CMD | SDHCI_RESET_DATA));
951     } else {
952         SdhciDoReset(host, SDHCI_RESET_ALL);
953     }
954 
955     host->pwr = 0;
956     host->irqEnable = SDHCI_INTERRUPT_BUS_POWER | SDHCI_INTERRUPT_DATA_END_BIT | SDHCI_INTERRUPT_DATA_CRC |
957                       SDHCI_INTERRUPT_DATA_TIMEOUT | SDHCI_INTERRUPT_INDEX | SDHCI_INTERRUPT_END_BIT |
958                       SDHCI_INTERRUPT_CRC | SDHCI_INTERRUPT_TIMEOUT | SDHCI_INTERRUPT_DATA_END |
959                       SDHCI_INTERRUPT_RESPONSE | SDHCI_INTERRUPT_AUTO_CMD_ERR;
960 
961     SdhciEnablePlugIrq(host, host->irqEnable);
962 
963     if (resetAll == false) {
964         host->clock = 0;
965     } else {
966         reg = SdhciReadw(host, MSHC_CTRL_R);
967         reg &= ~SDHC_CMD_CONFLIT_CHECK;
968         SdhciWritew(host, reg, MSHC_CTRL_R);
969 
970         reg = SdhciReadl(host, MBIU_CTRL_R);
971         reg &= ~(SDHCI_GM_WR_OSRC_LMT_MASK | SDHCI_GM_RD_OSRC_LMT_MASK | SDHCI_UNDEFL_INCR_EN);
972         reg |= SDHCI_GM_WR_OSRC_LMT_VAL | SDHCI_GM_RD_OSRC_LMT_VAL;
973         SdhciWritel(host, reg, MBIU_CTRL_R);
974 
975         reg = SdhciReadl(host, MULTI_CYCLE_R);
976         reg |= SDHCI_EDGE_DETECT_EN | SDHCI_DATA_DLY_EN;
977         reg &= ~SDHCI_CMD_DLY_EN;
978         SdhciWritel(host, reg, MULTI_CYCLE_R);
979     }
980 }
981 
SdhciReinit(struct SdhciHost *host)982 static void SdhciReinit(struct SdhciHost *host)
983 {
984     SdhciInit(host, true);
985 
986     if (host->flags & SDHCI_USING_RETUNING_TIMER) {
987         host->flags &= ~SDHCI_USING_RETUNING_TIMER;
988         host->mmc->maxBlkNum = SDHCI_MAX_BLK_NUM;
989     }
990     SdhciEnableCardDetection(host);
991 }
992 
SdhciEnablePresetValue(struct SdhciHost *host, bool enable)993 static void SdhciEnablePresetValue(struct SdhciHost *host, bool enable)
994 {
995     uint32_t reg;
996 
997     if (host->version < SDHCI_HOST_SPEC_300) {
998         return;
999     }
1000 
1001     if (host->presetEnabled != enable) {
1002         reg = SdhciReadw(host, HOST_CTRL2_R);
1003         if (enable == true) {
1004             reg |= SDHCI_PRESET_VAL_ENABLE;
1005         } else {
1006             reg &= ~SDHCI_PRESET_VAL_ENABLE;
1007         }
1008         SdhciWritew(host, reg, HOST_CTRL2_R);
1009 
1010         if (enable == true) {
1011             host->flags |= SDHCI_PV_ENABLED;
1012         } else {
1013             host->flags &= ~SDHCI_PV_ENABLED;
1014         }
1015         host->presetEnabled = enable;
1016     }
1017 }
1018 
SdhciSetPowerMode(struct MmcCntlr *cntlr, enum MmcPowerMode mode)1019 static int32_t SdhciSetPowerMode(struct MmcCntlr *cntlr, enum MmcPowerMode mode)
1020 {
1021     struct SdhciHost *host = (struct SdhciHost *)cntlr->priv;
1022     uint8_t pwr = SDHCI_POWER_330;
1023 
1024     if (mode == MMC_POWER_MODE_POWER_OFF) {
1025         SdhciWritel(host, 0, NORMAL_INT_SIGNAL_EN_R);
1026         SdhciReinit(host);
1027     } else {
1028         if (host->version >= SDHCI_HOST_SPEC_300) {
1029             SdhciEnablePresetValue(host, false);
1030         }
1031         if (host->pwr == SDHCI_POWER_330) {
1032             return HDF_SUCCESS;
1033         }
1034 
1035         host->pwr = pwr;
1036 
1037         SdhciWriteb(host, 0, PWR_CTRL_R);
1038         SdhciWriteb(host, pwr, PWR_CTRL_R);
1039         pwr |= SDHCI_POWER_ON;
1040         SdhciWriteb(host, pwr, PWR_CTRL_R);
1041         OsalMDelay(10);
1042     }
1043     return HDF_SUCCESS;
1044 }
1045 
SdhciSetBusWidth(struct MmcCntlr *cntlr, enum MmcBusWidth width)1046 static int32_t SdhciSetBusWidth(struct MmcCntlr *cntlr, enum MmcBusWidth width)
1047 {
1048     struct SdhciHost *host = (struct SdhciHost *)cntlr->priv;
1049     uint8_t val;
1050 
1051     val = SdhciReadb(host, HOST_CTRL1_R);
1052     if (width == BUS_WIDTH8) {
1053         val &= (~SDHCI_CTRL_4_BIT_BUS);
1054         if (host->version >= SDHCI_HOST_SPEC_300) {
1055             val |= SDHCI_CTRL_8_BIT_BUS;
1056         }
1057     } else {
1058         if (host->version >= SDHCI_HOST_SPEC_300) {
1059             val &= (~SDHCI_CTRL_8_BIT_BUS);
1060         }
1061         if (width == BUS_WIDTH4) {
1062             val |= SDHCI_CTRL_4_BIT_BUS;
1063         } else {
1064             val &= (~SDHCI_CTRL_4_BIT_BUS);
1065         }
1066     }
1067     SdhciWriteb(host, val, HOST_CTRL1_R);
1068     return HDF_SUCCESS;
1069 }
1070 
SdhciSetUhsSignaling(struct SdhciHost *host, enum MmcBusTiming timing)1071 static void SdhciSetUhsSignaling(struct SdhciHost *host, enum MmcBusTiming timing)
1072 {
1073     uint32_t val;
1074 
1075     val = SdhciReadw(host, HOST_CTRL2_R);
1076 
1077     /* Select Bus Speed Mode for host */
1078     val &= (~SDHCI_UHS_MASK);
1079     if (timing == BUS_TIMING_MMC_HS200 || timing == BUS_TIMING_UHS_SDR104) {
1080         val |= SDHCI_UHS_SDR104;
1081     } else if (timing == BUS_TIMING_UHS_SDR12) {
1082         val |= SDHCI_UHS_SDR12;
1083     } else if (timing == BUS_TIMING_UHS_SDR25) {
1084         val |= SDHCI_UHS_SDR25;
1085     } else if (timing == BUS_TIMING_UHS_SDR50) {
1086         val |= SDHCI_UHS_SDR50;
1087     } else if (timing == BUS_TIMING_UHS_DDR50 || timing == BUS_TIMING_UHS_DDR52) {
1088         val |= SDHCI_UHS_DDR50;
1089     } else if (timing == BUS_TIMING_MMC_HS400) {
1090         val |= SDHCI_HS400;
1091     }
1092     SdhciWritew(host, val, HOST_CTRL2_R);
1093 }
1094 
SdhciSetBusTiming(struct MmcCntlr *cntlr, enum MmcBusTiming timing)1095 static int32_t SdhciSetBusTiming(struct MmcCntlr *cntlr, enum MmcBusTiming timing)
1096 {
1097     struct SdhciHost *host = (struct SdhciHost *)cntlr->priv;
1098     uint32_t clockVal, ctrl1Val, ctrl2Val;
1099 
1100     ctrl1Val = SdhciReadb(host, HOST_CTRL1_R);
1101 
1102     if (timing >= BUS_TIMING_MMC_HS) {
1103         ctrl1Val |= SDHCI_CTRL_HIGH_SPEED;
1104     }
1105 
1106     if (host->version < SDHCI_HOST_SPEC_300) {
1107         SdhciWriteb(host, ctrl1Val, HOST_CTRL1_R);
1108         return HDF_SUCCESS;
1109     }
1110 
1111     if (host->presetEnabled == false) {
1112         SdhciWriteb(host, ctrl1Val, HOST_CTRL1_R);
1113         ctrl2Val = SdhciReadw(host, HOST_CTRL2_R);
1114         ctrl2Val &= ~SDHCI_DRV_TYPE_MASK;
1115 
1116         SdhciWritew(host, ctrl2Val, HOST_CTRL2_R);
1117     } else {
1118         clockVal = SdhciReadw(host, CLK_CTRL_R);
1119         clockVal &= ~SDHCI_CLK_CTRL_CLK_EN;
1120         SdhciWritew(host, clockVal, CLK_CTRL_R);
1121 
1122         SdhciWriteb(host, ctrl1Val, HOST_CTRL1_R);
1123         (void)SdhciSetClock(cntlr, host->clock);
1124     }
1125     clockVal = SdhciReadw(host, CLK_CTRL_R);
1126     clockVal &= ~SDHCI_CLK_CTRL_CLK_EN;
1127     SdhciWritew(host, clockVal, CLK_CTRL_R);
1128 
1129     SdhciSetUhsSignaling(host, timing);
1130     if (timing > BUS_TIMING_UHS_SDR12 && timing <= BUS_TIMING_UHS_DDR50) {
1131         SdhciEnablePresetValue(host, true);
1132     }
1133     (void)SdhciSetClock(cntlr, host->clock);
1134     return HDF_SUCCESS;
1135 }
1136 
SdhciSetSdioIrq(struct MmcCntlr *cntlr, bool enable)1137 static int32_t SdhciSetSdioIrq(struct MmcCntlr *cntlr, bool enable)
1138 {
1139     struct SdhciHost *host = (struct SdhciHost *)cntlr->priv;
1140 
1141     if (enable == true) {
1142         host->flags |= SDHCI_SDIO_IRQ_ENABLED;
1143     } else {
1144         host->flags &= ~SDHCI_SDIO_IRQ_ENABLED;
1145     }
1146 
1147     if ((host->flags & SDHCI_DEVICE_DEAD) == 0) {
1148         if (enable == true) {
1149             host->irqEnable |= SDHCI_INTERRUPT_CARD_INT;
1150         } else {
1151             host->irqEnable &= ~SDHCI_INTERRUPT_CARD_INT;
1152         }
1153         SdhciEnablePlugIrq(host, host->irqEnable);
1154     }
1155     return HDF_SUCCESS;
1156 }
1157 
SdhciHardwareReset(struct MmcCntlr *cntlr)1158 static int32_t SdhciHardwareReset(struct MmcCntlr *cntlr)
1159 {
1160     struct SdhciHost *host = (struct SdhciHost *)cntlr->priv;
1161 
1162     SdhciWritel(host, 0x0, EMMC_HW_RESET_R);
1163     OsalUDelay(10);
1164     SdhciWritel(host, 0x1, EMMC_HW_RESET_R);
1165     OsalUDelay(200);
1166 
1167     return HDF_SUCCESS;
1168 }
1169 
SdhciSystemInit(struct MmcCntlr *cntlr)1170 static int32_t SdhciSystemInit(struct MmcCntlr *cntlr)
1171 {
1172     struct SdhciHost *host = NULL;
1173 
1174     if (cntlr == NULL) {
1175         return HDF_ERR_INVALID_OBJECT;
1176     }
1177 
1178     host = (struct SdhciHost *)cntlr->priv;
1179     SdhciInit(host, true);
1180     SdhciEnableCardDetection(host);
1181     return HDF_SUCCESS;
1182 }
1183 
SdhciSetEnhanceStrobe(struct MmcCntlr *cntlr, bool enable)1184 static int32_t SdhciSetEnhanceStrobe(struct MmcCntlr *cntlr, bool enable)
1185 {
1186     struct SdhciHost *host = (struct SdhciHost *)cntlr->priv;
1187     uint32_t reg;
1188 
1189     reg = SdhciReadl(host, EMMC_CTRL_R);
1190     if (enable == true) {
1191         reg |= SDHCI_EMMC_CTRL_ENH_STROBE_EN;
1192     } else {
1193         reg &= ~SDHCI_EMMC_CTRL_ENH_STROBE_EN;
1194     }
1195     SdhciWritel(host, reg, EMMC_CTRL_R);
1196 
1197     reg = SdhciReadl(host, MULTI_CYCLE_R);
1198     if (enable == true) {
1199         reg |= SDHCI_CMD_DLY_EN;
1200     } else {
1201         reg &= ~SDHCI_CMD_DLY_EN;
1202     }
1203     SdhciWritel(host, reg, MULTI_CYCLE_R);
1204     return HDF_SUCCESS;
1205 }
1206 
SdhciSwitchVoltage(struct MmcCntlr *cntlr, enum MmcVolt volt)1207 static int32_t SdhciSwitchVoltage(struct MmcCntlr *cntlr, enum MmcVolt volt)
1208 {
1209     uint16_t ctrl;
1210     struct SdhciHost *host = (struct SdhciHost *)cntlr->priv;
1211 
1212     if (cntlr->devType == MMC_DEV_EMMC) {
1213         ctrl = SdhciReadw(host, HOST_CTRL2_R);
1214         if (volt == VOLT_1V8) {
1215             ctrl |= SDHCI_VDD_180;
1216             SdhciWritew(host, ctrl, HOST_CTRL2_R);
1217         } else {
1218             ctrl &= ~SDHCI_VDD_180;
1219             SdhciWritew(host, ctrl, HOST_CTRL2_R);
1220         }
1221     } else {
1222         if (volt == VOLT_3V3) {
1223             return HDF_SUCCESS;
1224         }
1225         return HDF_FAILURE;
1226     }
1227     return HDF_SUCCESS;
1228 }
1229 
SdhciDevReadOnly(struct MmcCntlr *cntlr)1230 static bool SdhciDevReadOnly(struct MmcCntlr *cntlr)
1231 {
1232     uint32_t val;
1233     bool readOnly = true;
1234     struct SdhciHost *host = (struct SdhciHost *)cntlr->priv;
1235 
1236     if (host->flags & SDHCI_DEVICE_DEAD) {
1237         readOnly = false;
1238     } else {
1239         val = SdhciReadl(host, PSTATE_R);
1240         readOnly = ((val & SDHCI_WRITE_PROTECT) > 0 ? false : true);
1241     }
1242 
1243     if (host->quirks.bits.invertedWriteProtect > 0) {
1244         return (!readOnly);
1245     }
1246     return readOnly;
1247 }
1248 
SdhciDevBusy(struct MmcCntlr *cntlr)1249 static bool SdhciDevBusy(struct MmcCntlr *cntlr)
1250 {
1251     struct SdhciHost *host = (struct SdhciHost *)cntlr->priv;
1252     uint32_t state;
1253 
1254     /* Check whether DAT[0] is 0 */
1255     state = SdhciReadl(host, PSTATE_R);
1256     return !(state & SDHCI_DATA_0_LEVEL_MASK);
1257 }
1258 
SdhciWaitDrvDllLock(uint32_t id)1259 static void SdhciWaitDrvDllLock(uint32_t id)
1260 {
1261     uint32_t i, val;
1262     uint32_t offset[] = { PERI_SD_DRV_DLL_CTRL, PERI_SDIO_DRV_DLL_CTRL };
1263 
1264     if (id >= (sizeof(offset) / sizeof(offset[0]))) {
1265         return;
1266     }
1267 
1268     for (i = 0; i < SDHCI_CLK_CTRL_RETRY_TIMES; i++) {
1269         val = OSAL_READL(offset[id]);
1270         if ((val & SDHCI_DRV_DLL_LOCK) > 0) {
1271             return;
1272         }
1273         OsalMDelay(1);
1274     }
1275     HDF_LOGD("host%u: DRV DLL not locked.", id);
1276 }
1277 
SdhciEnableSamplDll(uint32_t id)1278 static void SdhciEnableSamplDll(uint32_t id)
1279 {
1280     uint32_t val;
1281     uint32_t offset[] = { PERI_CRG125, PERI_CRG139 };
1282 
1283     if (id >= (sizeof(offset) / sizeof(offset[0]))) {
1284         return;
1285     }
1286 
1287     val = OSAL_READL(offset[id]);
1288     val |= SDHCI_SAMPL_DLL_DEV_EN;
1289     OSAL_WRITEL(val, offset[id]);
1290 }
1291 
SdhciPreTune(struct SdhciHost *host)1292 static void SdhciPreTune(struct SdhciHost *host)
1293 {
1294     uint32_t val;
1295 
1296     val = SdhciReadl(host, NORMAL_INT_STAT_EN_R);
1297     val |= SDHCI_INTERRUPT_DATA_AVAIL;
1298     SdhciWritel(host, val, NORMAL_INT_STAT_EN_R);
1299 
1300     val = SdhciReadl(host, NORMAL_INT_SIGNAL_EN_R);
1301     val |= SDHCI_INTERRUPT_DATA_AVAIL;
1302     SdhciWritel(host, val, NORMAL_INT_SIGNAL_EN_R);
1303 
1304     SdhciWaitDrvDllLock(host->hostId);
1305     SdhciEnableSamplDll(host->hostId);
1306     SdhciEnableSample(host);
1307 }
1308 
SdhciEnableEdgeTune(struct SdhciHost *host)1309 static void SdhciEnableEdgeTune(struct SdhciHost *host)
1310 {
1311     uint32_t val;
1312     uint32_t offset[] = { PERI_CRG126, PERI_CRG135 };
1313 
1314     if (host->hostId >= (sizeof(offset) / sizeof(offset[0]))) {
1315         return;
1316     }
1317     val = OSAL_READL(offset[host->hostId]);
1318     val = (val & (~SDHCI_SAMPLB_DLL_CLK_MASK)) | SDHCI_SAMPLB_SEL(SDHCI_SAMPLB_DLL_CLK);
1319     OSAL_WRITEL(val, offset[host->hostId]);
1320     val = SdhciReadl(host, MULTI_CYCLE_R);
1321     val |= SDHCI_EDGE_DETECT_EN | SDHCI_DATA_DLY_EN;
1322     val &= ~SDHCI_CMD_DLY_EN;
1323     SdhciWritel(host, val, MULTI_CYCLE_R);
1324 }
1325 
SdhciWaitSamplDllReady(uint32_t id)1326 void SdhciWaitSamplDllReady(uint32_t id)
1327 {
1328     uint32_t offset[] = { PERI_SD_SAMPL_DLL_STATUS, PERI_SDIO_SAMPL_DLL_STATUS };
1329     uint32_t i, val;
1330 
1331     if (id >= (sizeof(offset) / sizeof(offset[0]))) {
1332         return;
1333     }
1334 
1335     for (i = 0; i < SDHCI_CLK_CTRL_RETRY_TIMES; i++) {
1336         val = OSAL_READL(offset[id]);
1337         if ((val & SDHCI_SAMPL_DLL_DEV_READY) > 0) {
1338             return;
1339         }
1340         OsalMDelay(1);
1341     }
1342     HDF_LOGD("host%u: SAMPL DLL not ready.", id);
1343 }
1344 
SdhciCardClk(struct SdhciHost *host, bool action)1345 static void SdhciCardClk(struct SdhciHost *host, bool action)
1346 {
1347     uint32_t value;
1348 
1349     value = SdhciReadl(host, CLK_CTRL_R);
1350     if (action == false) {
1351         /* close the clock gate */
1352         value &= ~SDHCI_CLK_CTRL_CLK_EN;
1353     } else {
1354         /* open the clk of interface */
1355         value |= SDHCI_CLK_CTRL_CLK_EN;
1356     }
1357     SdhciWritel(host, value, CLK_CTRL_R);
1358 }
1359 
SdhciSelectSamplPhase(struct SdhciHost *host, uint32_t phase)1360 static void SdhciSelectSamplPhase(struct SdhciHost *host, uint32_t phase)
1361 {
1362     SdhciCardClk(host, false);
1363     SdhciSetSampPhase(host, phase);
1364     SdhciWaitSamplDllReady(host->hostId);
1365     SdhciCardClk(host, true);
1366     OsalUDelay(1);
1367 }
1368 
SdhciDisEdgeTune(struct SdhciHost *host)1369 static void SdhciDisEdgeTune(struct SdhciHost *host)
1370 {
1371     uint32_t val;
1372 
1373     val = SdhciReadl(host, MULTI_CYCLE_R);
1374     val &= ~SDHCI_EDGE_DETECT_EN;
1375     SdhciWritel(host, val, MULTI_CYCLE_R);
1376 }
1377 
SdhciPostTune(struct SdhciHost *host)1378 static void SdhciPostTune(struct SdhciHost *host)
1379 {
1380     uint32_t val;
1381     uint16_t ctrl;
1382 
1383     ctrl = SdhciReadw(host, HOST_CTRL2_R);
1384     ctrl |= SDHCI_TUNED_CLK;
1385     SdhciWritew(host, ctrl, HOST_CTRL2_R);
1386 
1387     val = SdhciReadl(host, NORMAL_INT_STAT_EN_R);
1388     val &= ~SDHCI_INTERRUPT_DATA_AVAIL;
1389     SdhciWritel(host, val, NORMAL_INT_STAT_EN_R);
1390     val = SdhciReadl(host, NORMAL_INT_SIGNAL_EN_R);
1391     val &= ~SDHCI_INTERRUPT_DATA_AVAIL;
1392     SdhciWritel(host, val, NORMAL_INT_SIGNAL_EN_R);
1393 }
1394 
SdhciDoTune(struct SdhciHost *host, uint32_t opcode, uint32_t start, uint32_t end)1395 static void SdhciDoTune(struct SdhciHost *host, uint32_t opcode, uint32_t start, uint32_t end)
1396 {
1397     int32_t err;
1398     int32_t prevError = 0;
1399     uint32_t phase, fall, rise, fallUpdateFlag, index;
1400 
1401     fall = start;
1402     rise = end;
1403     fallUpdateFlag = 0;
1404     for (index = start; index <= end; index++) {
1405         SdhciSelectSamplPhase(host, index % SDHCI_PHASE_SCALE);
1406         err = MmcSendTuning(host->mmc, opcode, true);
1407         if (err != HDF_SUCCESS) {
1408             HDF_LOGD("send tuning CMD%u fail! phase:%u err:%d.", opcode, index, err);
1409         }
1410         if (err && index == start) {
1411             if (!fallUpdateFlag) {
1412                 fallUpdateFlag = 1;
1413                 fall = start;
1414             }
1415         } else {
1416             if (!prevError && err && !fallUpdateFlag) {
1417                 fallUpdateFlag = 1;
1418                 fall = index;
1419             }
1420         }
1421 
1422         if (prevError && !err) {
1423             rise = index;
1424         }
1425 
1426         if (err && index == end) {
1427             rise = end;
1428         }
1429         prevError = err;
1430     }
1431 
1432     phase = ((fall + rise) / SDHCI_DIV_MIDDLE + SDHCI_PHASE_SCALE_GAP) % SDHCI_PHASE_SCALE;
1433     host->tuningPhase = phase;
1434     SdhciSelectSamplPhase(host, phase);
1435     SdhciPostTune(host);
1436 }
1437 
SdhciTune(struct MmcCntlr *cntlr, uint32_t cmdCode)1438 static int32_t SdhciTune(struct MmcCntlr *cntlr, uint32_t cmdCode)
1439 {
1440     struct SdhciHost *host = (struct SdhciHost *)cntlr->priv;
1441     uint32_t index, val;
1442     bool found = false;
1443     bool prevFound = false;
1444     uint32_t edgeP2F = 0;
1445     uint32_t start = 0;
1446     uint32_t edgeF2P = SDHCI_PHASE_SCALE / SDHCI_PHASE_SCALE_TIMES;
1447     uint32_t end = SDHCI_PHASE_SCALE / SDHCI_PHASE_SCALE_TIMES;
1448     int32_t err;
1449 
1450     SdhciPreTune(host);
1451     SdhciEnableEdgeTune(host);
1452     for (index = 0; index <= end; index++) {
1453         SdhciSelectSamplPhase(host, index * SDHCI_PHASE_SCALE_TIMES);
1454         err = MmcSendTuning(cntlr, cmdCode, true);
1455         if (err == HDF_SUCCESS) {
1456             val = SdhciReadl(host, MULTI_CYCLE_R);
1457             found = ((val & SDHCI_FOUND_EDGE) > 0 ? true : false);
1458         } else {
1459             found = true;
1460         }
1461 
1462         if (prevFound == true && found == false) {
1463             edgeF2P = index;
1464         } else if (prevFound == false && found == true) {
1465             edgeP2F = index;
1466         }
1467         if ((edgeP2F != start) && (edgeF2P != end)) {
1468             break;
1469         }
1470         prevFound = found;
1471         found = false;
1472     }
1473 
1474     if ((edgeP2F == start) && (edgeF2P == end)) {
1475         HDF_LOGE("host%u: tuning failed! can not found edge!", host->hostId);
1476         return HDF_FAILURE;
1477     }
1478     SdhciDisEdgeTune(host);
1479 
1480     start = edgeP2F * SDHCI_PHASE_SCALE_TIMES;
1481     end = edgeF2P * SDHCI_PHASE_SCALE_TIMES;
1482     if (end <= start) {
1483         end += SDHCI_PHASE_SCALE;
1484     }
1485 
1486     SdhciDoTune(host, cmdCode, start, end);
1487     return HDF_SUCCESS;
1488 }
1489 
SdhciRescanSdioDev(struct MmcCntlr *cntlr)1490 static int32_t SdhciRescanSdioDev(struct MmcCntlr *cntlr)
1491 {
1492     struct SdhciHost *host = NULL;
1493 
1494     if ((cntlr == NULL) || (cntlr->priv == NULL)) {
1495         return HDF_ERR_INVALID_OBJECT;
1496     }
1497 
1498     host = (struct SdhciHost *)cntlr->priv;
1499     if (host->waitForEvent == true) {
1500         (void)SDHCI_EVENT_SIGNAL(&host->sdhciEvent, SDHCI_PEND_ACCIDENT);
1501     }
1502 
1503     return MmcCntlrAddSdioRescanMsgToQueue(cntlr);
1504 }
1505 
1506 static struct MmcCntlrOps g_sdhciHostOps = {
1507     .request = SdhciDoRequest,
1508     .setClock = SdhciSetClock,
1509     .setPowerMode = SdhciSetPowerMode,
1510     .setBusWidth = SdhciSetBusWidth,
1511     .setBusTiming = SdhciSetBusTiming,
1512     .setSdioIrq = SdhciSetSdioIrq,
1513     .hardwareReset = SdhciHardwareReset,
1514     .systemInit = SdhciSystemInit,
1515     .setEnhanceStrobe = SdhciSetEnhanceStrobe,
1516     .switchVoltage = SdhciSwitchVoltage,
1517     .devReadOnly = SdhciDevReadOnly,
1518     .devPlugged = SdhciCardPlugged,
1519     .devBusy = SdhciDevBusy,
1520     .tune = SdhciTune,
1521     .rescanSdioDev = SdhciRescanSdioDev,
1522 };
1523 
SdhciDeleteHost(struct SdhciHost *host)1524 static void SdhciDeleteHost(struct SdhciHost *host)
1525 {
1526     struct MmcCntlr *cntlr = NULL;
1527 
1528     if (host == NULL) {
1529         return;
1530     }
1531 
1532     cntlr = host->mmc;
1533     if (cntlr != NULL) {
1534         if (cntlr->curDev != NULL) {
1535             MmcDeviceRemove(cntlr->curDev);
1536             OsalMemFree(cntlr->curDev);
1537             cntlr->curDev = NULL;
1538         }
1539         MmcCntlrRemove(cntlr);
1540         cntlr->hdfDevObj = NULL;
1541         cntlr->priv = NULL;
1542         cntlr->ops = NULL;
1543         OsalMemFree(cntlr);
1544         host->mmc = NULL;
1545     }
1546 
1547     OsalUnregisterIrq(host->irqNum, host);
1548     if (host->admaDesc != NULL) {
1549         OsalMemFree(host->admaDesc);
1550         host->admaDesc = NULL;
1551     }
1552     if (host->base != NULL) {
1553         OsalIoUnmap(host->base);
1554     }
1555 
1556     (void)SDHCI_EVENT_DELETE(&host->sdhciEvent);
1557     (void)OsalMutexDestroy(&host->mutex);
1558     OsalMemFree(host);
1559 }
1560 
SdhciHostParse(struct SdhciHost *host, struct HdfDeviceObject *obj)1561 static int32_t SdhciHostParse(struct SdhciHost *host, struct HdfDeviceObject *obj)
1562 {
1563     const struct DeviceResourceNode *node = NULL;
1564     struct DeviceResourceIface *drsOps = NULL;
1565     int32_t ret;
1566     uint32_t regBase, regSize;
1567 
1568     if (obj == NULL || host == NULL) {
1569         HDF_LOGE("%s: input param is NULL.", __func__);
1570         return HDF_FAILURE;
1571     }
1572 
1573     node = obj->property;
1574     if (node == NULL) {
1575         HDF_LOGE("%s: drs node is NULL.", __func__);
1576         return HDF_FAILURE;
1577     }
1578     drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
1579     if (drsOps == NULL || drsOps->GetUint32 == NULL) {
1580         HDF_LOGE("%s: invalid drs ops fail!", __func__);
1581         return HDF_FAILURE;
1582     }
1583 
1584     ret = drsOps->GetUint32(node, "regBasePhy", &regBase, 0);
1585     if (ret != HDF_SUCCESS) {
1586         HDF_LOGE("%s: read regBasePhy fail!", __func__);
1587         return ret;
1588     }
1589     ret = drsOps->GetUint32(node, "regSize", &regSize, 0);
1590     if (ret != HDF_SUCCESS) {
1591         HDF_LOGE("%s: read regSize fail!", __func__);
1592         return ret;
1593     }
1594     host->base = OsalIoRemap(regBase, regSize);
1595     if (host->base == NULL) {
1596         HDF_LOGE("%s: ioremap regBase fail!", __func__);
1597         return HDF_ERR_IO;
1598     }
1599 
1600     ret = drsOps->GetUint32(node, "irqNum", &(host->irqNum), 0);
1601     if (ret != HDF_SUCCESS) {
1602         HDF_LOGE("%s: read irqNum fail!", __func__);
1603     }
1604 
1605     ret = drsOps->GetUint32(node, "quirks", &(host->quirks.quirksData), 0);
1606     if (ret != HDF_SUCCESS) {
1607         HDF_LOGD("%s: read quirks fail!", __func__);
1608         host->quirks.quirksData = 0;
1609     }
1610     return ret;
1611 }
1612 
SdhciCrgInit(struct SdhciHost *host)1613 static void SdhciCrgInit(struct SdhciHost *host)
1614 {
1615     uint32_t value, reg;
1616     uint32_t cfgArray[] = {PERI_CRG125, PERI_CRG139};
1617     if (host->hostId >= SDHCI_MAX_HOST_NUM) {
1618         return;
1619     }
1620 
1621     /* open the clock gate */
1622     reg = cfgArray[host->hostId];
1623     value = OSAL_READL(reg);
1624     value |= SDHCI_EMMC_CKEN;
1625     OSAL_WRITEL(value, reg);
1626 
1627     /* crg_reset, dll_reset, sampl_reset */
1628     reg = cfgArray[host->hostId];
1629     value = OSAL_READL(reg);
1630     value |= SDHCI_EMMC_CRG_REQ;
1631     value |= SDHCI_EMMC_DLL_RST;
1632     OSAL_WRITEL(value, reg);
1633 
1634     /* wait the card clk close for 25us */
1635     HalDelayUs(25);
1636 
1637     /* reset of host contorl is done */
1638     value = OSAL_READL(reg);
1639     value &= ~SDHCI_EMMC_CRG_REQ;
1640     OSAL_WRITEL(value, reg);
1641     HalDelayUs(25);
1642 
1643     /* close the clock gate */
1644     SdhciCardClk(host, false);
1645 
1646     if (host->mmc->devType == MMC_DEV_EMMC) {
1647         (void)SdhciSelectClock(host, SDHCI_MMC_FREQ_150M);
1648     } else {
1649         (void)SdhciSelectClock(host, SDHCI_MMC_FREQ_50M);
1650     }
1651 
1652     /* SAM/DRV */
1653     SdhciSetDrvPhase(host->hostId, 0x10);
1654     /* wait the clock switch over for 25us */
1655     OsalUDelay(25);
1656 
1657     /* open the clk of interface */
1658     SdhciCardClk(host, true);
1659 
1660     /* open the clk of card */
1661     value = SdhciReadl(host, CLK_CTRL_R);
1662     value |= (SDHCI_CLK_CTRL_INT_CLK_EN | SDHCI_CLK_CTRL_CLK_EN | SDHCI_CLK_CTRL_PLL_EN);
1663     SdhciWritel(host, value, CLK_CTRL_R);
1664     /* wait the phase switch over, 75us */
1665     OsalUDelay(75);
1666 }
1667 
SdhciUpdateCapFlag(struct SdhciHost *host, uint32_t cap)1668 static void SdhciUpdateCapFlag(struct SdhciHost *host, uint32_t cap)
1669 {
1670     struct MmcCntlr *mmc = host->mmc;
1671 
1672     if (cap & SDHCI_SUPPORT_SDMA) {
1673         host->flags |= SDHCI_USE_SDMA;
1674     }
1675 
1676     if ((host->version >= SDHCI_HOST_SPEC_200) && (cap & SDHCI_SUPPORT_ADMA2)) {
1677         host->flags |= SDHCI_USE_ADMA;
1678         if (cap & SDHCI_SUPPORT_64BIT) {
1679             host->flags |= SDHCI_USE_64BIT_ADMA;
1680         }
1681     }
1682 
1683     if ((host->version >= SDHCI_HOST_SPEC_300 && (host->flags & SDHCI_USE_ADMA) > 0) ||
1684         (host->flags & SDHCI_USE_SDMA) == 0) {
1685         host->flags |= SDHCI_AUTO_CMD23;
1686         HDF_LOGD("Auto-CMD23 available!");
1687     }
1688 
1689     host->flags |= SDHCI_HOST_IRQ_STATUS;
1690     if (mmc->devType == MMC_DEV_SDIO) {
1691         host->flags &= ~(SDHCI_SUPPORT_SDMA | SDHCI_AUTO_CMD23 | SDHCI_AUTO_CMD12);
1692     } else {
1693         host->flags &= ~(SDHCI_SUPPORT_SDMA);
1694         host->flags |= SDHCI_AUTO_CMD23;
1695     }
1696 }
1697 
SdhciFillAdmaInfo(struct SdhciHost *host)1698 static int32_t SdhciFillAdmaInfo(struct SdhciHost *host)
1699 {
1700     if (host->flags & SDHCI_USE_ADMA) {
1701         host->admaMaxDesc = SDHCI_ADMA_MAX_DESC;
1702         host->admaDescSize = SDHCI_ADMA_DEF_SIZE;
1703 
1704         if (host->flags & SDHCI_USE_64BIT_ADMA) {
1705             host->admaDescLineSize = SDHCI_ADMA_64BIT_LINE_SIZE;
1706         } else {
1707             host->admaDescLineSize = SDHCI_ADMA_LINE_SIZE;
1708         }
1709         host->admaDescSize = (host->admaMaxDesc * 2 + 1) * host->admaDescLineSize;
1710         host->admaDesc = (void *)OsalMemAllocAlign(CACHE_ALIGNED_SIZE, ALIGN(host->admaDescSize, CACHE_ALIGNED_SIZE));
1711         if (host->admaDesc == NULL) {
1712             HDF_LOGE("SdhciFillAdmaInfo: allocate ADMA buffer fail!");
1713             return HDF_ERR_MALLOC_FAIL;
1714         }
1715     } else {
1716         HDF_LOGE("SdhciFillAdmaInfo: Warning! ADMA not support!");
1717         return HDF_ERR_NOT_SUPPORT;
1718     }
1719     return HDF_SUCCESS;
1720 }
1721 
SdhciFillClkInfo(struct SdhciHost *host, uint32_t cap1, uint32_t cap2)1722 static void SdhciFillClkInfo(struct SdhciHost *host, uint32_t cap1, uint32_t cap2)
1723 {
1724     struct MmcCntlr *mmc = host->mmc;
1725 
1726     if (host->version >= SDHCI_HOST_SPEC_300) {
1727         host->maxClk = (cap1 & SDHCI_BASIC_FREQ_OF_CLK_MASK) >> SDHCI_BASIC_FREQ_OF_CLK_SHIFT;
1728     } else {
1729         host->maxClk = (cap1 & SDHCI_CLK_BASE_MASK) >> SDHCI_BASIC_FREQ_OF_CLK_SHIFT;
1730     }
1731     /* unit: MHz */
1732     host->maxClk *= 1000000;
1733     host->clkMul = (cap2 & SDHCI_CLK_MUL_MASK) >> SDHCI_CLK_MUL_SHIFT;
1734 
1735     if (host->clkMul) {
1736         host->clkMul += 1;
1737     }
1738     if (mmc->freqMax == 0) {
1739         mmc->freqMax = host->maxClk;
1740     } else {
1741         host->maxClk = mmc->freqMax;
1742     }
1743 
1744     if (mmc->freqMin == 0) {
1745         if (host->version >= SDHCI_HOST_SPEC_300) {
1746             if (host->clkMul) {
1747                 mmc->freqMin = (host->maxClk * host->clkMul) / 1024;
1748                 mmc->freqMax = host->maxClk * host->clkMul;
1749             } else {
1750                 mmc->freqMin = host->maxClk / SDHCI_MAX_DIV_SPEC_300;
1751             }
1752         } else {
1753             mmc->freqMin = host->maxClk / SDHCI_MAX_DIV_SPEC_200;
1754         }
1755     }
1756 }
1757 
SdhciUpdateDrvCap(struct SdhciHost *host, uint32_t cap1, uint32_t cap2)1758 static void SdhciUpdateDrvCap(struct SdhciHost *host, uint32_t cap1, uint32_t cap2)
1759 {
1760     struct MmcCntlr *mmc = host->mmc;
1761 
1762     if (cap1 & SDHCI_SUPPORT_HISPD) {
1763         mmc->caps.bits.highSpeed = 1;
1764     }
1765 
1766     if (cap2 & SDHCI_SUPPORT_DRIVER_TYPE_A) {
1767         mmc->caps.bits.driverTypeA = 1;
1768     }
1769     if (cap2 & SDHCI_SUPPORT_DRIVER_TYPE_C) {
1770         mmc->caps.bits.driverTypeC = 1;
1771     }
1772     if (cap2 & SDHCI_SUPPORT_DRIVER_TYPE_D) {
1773         mmc->caps.bits.driverTypeD = 1;
1774     }
1775 
1776     if (mmc->devType == MMC_DEV_EMMC) {
1777         if (cap1 & SDHCI_SUPPORT_VDD_180) {
1778             mmc->ocrDef.bits.vdd1v65To1v95 = 1;
1779             HDF_LOGD("VDD1.8 support.");
1780         }
1781     }
1782 
1783     if (host->flags & SDHCI_USE_ADMA) {
1784         mmc->maxReqSize = host->admaMaxDesc * 65536;
1785     }
1786 
1787     mmc->maxBlkSize = (cap1 & SDHCI_MAX_BLOCK_SIZE_MASK) >> SDHCI_MAX_BLOCK_SIZE_SHIFT;
1788     mmc->maxBlkSize = MMC_SEC_SIZE << mmc->maxBlkSize;
1789     mmc->maxBlkNum = (mmc->maxReqSize / mmc->maxBlkSize);
1790 }
1791 
SdhciEnableSdioIrqNoLock(struct SdhciHost *host, bool enable)1792 static void SdhciEnableSdioIrqNoLock(struct SdhciHost *host, bool enable)
1793 {
1794     if (!(host->flags & SDHCI_DEVICE_DEAD)) {
1795         if (enable == true) {
1796             host->irqEnable |= SDHCI_INTERRUPT_CARD_INT;
1797         } else {
1798             host->irqEnable &= ~SDHCI_INTERRUPT_CARD_INT;
1799         }
1800         SdhciEnablePlugIrq(host, host->irqEnable);
1801     }
1802 }
1803 
SdhciSaveCommandResp(struct SdhciHost *host, struct MmcCmd *cmd)1804 static void SdhciSaveCommandResp(struct SdhciHost *host, struct MmcCmd *cmd)
1805 {
1806     uint32_t i;
1807 
1808     for (i = 0; i < MMC_CMD_RESP_SIZE; i++) {
1809         cmd->resp[i] = SdhciReadl(host, RESP01_R + (3 - i) * 4) << 8;
1810         if (i != 3) {
1811             cmd->resp[i] |= SdhciReadb(host, RESP01_R + (3 - i) * 4 - 1);
1812         }
1813     }
1814 }
1815 
SdhciFinishCommand(struct SdhciHost *host)1816 static void SdhciFinishCommand(struct SdhciHost *host)
1817 {
1818     struct MmcCmd *cmd = host->cmd;
1819 
1820     if (cmd == NULL) {
1821         return;
1822     }
1823 
1824     if (cmd->respType & RESP_PRESENT) {
1825         if (cmd->respType & RESP_136) {
1826             SdhciSaveCommandResp(host, cmd);
1827         } else {
1828             cmd->resp[0] = SdhciReadl(host, RESP01_R);
1829         }
1830     }
1831 
1832     if (cmd->data == NULL || cmd->cmdCode == STOP_TRANSMISSION) {
1833         SdhciTaskletFinish(host);
1834     }
1835 }
1836 
SdhciCmdIrq(struct SdhciHost *host, uint32_t intMask)1837 static void SdhciCmdIrq(struct SdhciHost *host, uint32_t intMask)
1838 {
1839     if (host->cmd == NULL) {
1840         return;
1841     }
1842 
1843     if (intMask & SDHCI_INTERRUPT_TIMEOUT) {
1844         host->cmd->returnError = HDF_ERR_TIMEOUT;
1845     } else if (intMask & (SDHCI_INTERRUPT_CRC | SDHCI_INTERRUPT_END_BIT | SDHCI_INTERRUPT_INDEX)) {
1846         host->cmd->returnError = HDF_MMC_ERR_ILLEGAL_SEQ;
1847     }
1848 
1849     if (host->cmd->data == NULL && host->cmd->returnError != HDF_SUCCESS) {
1850         SdhciTaskletFinish(host);
1851         return;
1852     }
1853 
1854     if (host->cmd->respType & RESP_BUSY) {
1855         return;
1856     }
1857 
1858     if (intMask & SDHCI_INTERRUPT_RESPONSE) {
1859         SdhciFinishCommand(host);
1860     }
1861 }
1862 
SdhciFinishData(struct SdhciHost *host)1863 static void SdhciFinishData(struct SdhciHost *host)
1864 {
1865     struct MmcData *data = host->cmd->data;
1866 
1867     if (data->sendStopCmd == true) {
1868         if (data->returnError != HDF_SUCCESS) {
1869             SdhciDoReset(host, SDHCI_RESET_CMD);
1870             SdhciDoReset(host, SDHCI_RESET_DATA);
1871         }
1872         SdhciExecCmd(host, &(data->stopCmd));
1873     } else {
1874         SdhciTaskletFinish(host);
1875     }
1876 }
1877 
SdhciDataIrq(struct SdhciHost *host, uint32_t intMask)1878 static void SdhciDataIrq(struct SdhciHost *host, uint32_t intMask)
1879 {
1880     uint32_t command;
1881     struct MmcCmd *cmd = host->cmd;
1882 
1883     if (cmd->data == NULL || (cmd->cmdCode == STOP_TRANSMISSION)) {
1884         if ((cmd->respType & RESP_BUSY)) {
1885             if (intMask & SDHCI_INTERRUPT_DATA_TIMEOUT) {
1886                 cmd->returnError = HDF_ERR_TIMEOUT;
1887                 SdhciTaskletFinish(host);
1888                 return;
1889             }
1890             if (intMask & SDHCI_INTERRUPT_DATA_END) {
1891                 SdhciFinishCommand(host);
1892                 return;
1893             }
1894         }
1895     }
1896     if (cmd->data == NULL) {
1897         return;
1898     }
1899 
1900     if (intMask & SDHCI_INTERRUPT_DATA_TIMEOUT) {
1901         cmd->data->returnError = HDF_ERR_TIMEOUT;
1902     } else if (intMask & SDHCI_INTERRUPT_END_BIT) {
1903         cmd->data->returnError = HDF_MMC_ERR_ILLEGAL_SEQ;
1904     } else if ((intMask & SDHCI_INTERRUPT_DATA_CRC)) {
1905         cmd->data->returnError = HDF_MMC_ERR_ILLEGAL_SEQ;
1906     } else if (intMask & SDHCI_INTERRUPT_ADMA_ERROR) {
1907         cmd->data->returnError = HDF_ERR_IO;
1908     }
1909 
1910     if (cmd->data->returnError != HDF_SUCCESS) {
1911         command = SDHCI_PARSE_CMD(SdhciReadw(host, CMD_R));
1912         if (command != SD_CMD_SEND_TUNING_BLOCK && command != SEND_TUNING_BLOCK_HS200) {
1913             HDF_LOGE("err = 0x%x, cmd = %u, interrupt = 0x%x.", cmd->data->returnError, command, intMask);
1914             SdhciDumpregs(host);
1915         }
1916         SdhciFinishData(host);
1917     } else {
1918         if (intMask & SDHCI_INTERRUPT_DATA_END) {
1919             SdhciFinishData(host);
1920         } else {
1921             HDF_LOGE("do check here! intmask = 0x%x.", intMask);
1922         }
1923     }
1924 }
1925 
SdhciIrqHandler(uint32_t irq, void *data)1926 static uint32_t SdhciIrqHandler(uint32_t irq, void *data)
1927 {
1928     struct SdhciHost *host = (struct SdhciHost *)data;
1929     uint32_t intMask;
1930     (void)irq;
1931 
1932     if (host == NULL || host->mmc == NULL) {
1933         HDF_LOGE("SdhciIrqHandler: data is null!");
1934         return HDF_SUCCESS;
1935     }
1936 
1937     while ((intMask = SdhciReadl(host, NORMAL_INT_STAT_R)) != 0) {
1938         SdhciWritel(host, intMask, NORMAL_INT_STAT_R);
1939         if (intMask & SDHCI_CART_PLUG_STATE) {
1940             host->irqEnable &= ~SDHCI_CART_PLUG_STATE;
1941             host->irqEnable |= SDHCI_PLUG_STATE(host) ? SDHCI_INTERRUPT_CARD_REMOVE : SDHCI_INTERRUPT_CARD_INSERT;
1942             SdhciEnablePlugIrq(host, host->irqEnable);
1943             SdhciWritel(host, intMask & SDHCI_CART_PLUG_STATE, NORMAL_INT_STAT_R);
1944             MmcCntlrAddPlugMsgToQueue(host->mmc);
1945             if (host->waitForEvent) {
1946                 (void)SDHCI_EVENT_SIGNAL(&host->sdhciEvent, SDHCI_PEND_ACCIDENT);
1947             }
1948         }
1949 
1950         if (intMask & SDHCI_INT_CMD_MASK) {
1951             SdhciCmdIrq(host, (intMask & SDHCI_INT_CMD_MASK));
1952         }
1953         if (intMask & SDHCI_INT_DATA_MASK) {
1954             SdhciDataIrq(host, (intMask & SDHCI_INT_DATA_MASK));
1955         }
1956         if (intMask & SDHCI_INTERRUPT_BUS_POWER) {
1957             HDF_LOGD("host%u: card is consuming too much power!", host->hostId);
1958         }
1959         if (intMask & SDHCI_INTERRUPT_CARD_INT) {
1960             SdhciEnableSdioIrqNoLock(host, false);
1961             MmcCntlrNotifySdioIrqThread(host->mmc);
1962         }
1963     }
1964     return HDF_SUCCESS;
1965 }
1966 
SdhciHostInit(struct SdhciHost *host, struct MmcCntlr *cntlr)1967 static int32_t SdhciHostInit(struct SdhciHost *host, struct MmcCntlr *cntlr)
1968 {
1969     int32_t ret;
1970     uint32_t Capability1;
1971     uint32_t Capability2 = 0;
1972 
1973     host->hostId = (uint32_t)cntlr->index;
1974     if (SDHCI_EVENT_INIT(&host->sdhciEvent) != HDF_SUCCESS) {
1975         HDF_LOGE("SdhciHostInit: sdhciEvent init fail!\n");
1976         return HDF_FAILURE;
1977     }
1978     if (OsalMutexInit(&host->mutex) != HDF_SUCCESS) {
1979         HDF_LOGE("SdhciHostInit: init mutex lock fail!");
1980         return HDF_FAILURE;
1981     }
1982 
1983     SdhciCrgInit(host);
1984     host->version = SdhciReadw(host, HOST_VERSION_R);
1985     host->version = (host->version & SDHCI_HOST_SPEC_VER_MASK);
1986     Capability1 = SdhciReadl(host, CAPABILITIES1_R);
1987     if (host->version >= SDHCI_HOST_SPEC_300) {
1988         Capability2 = SdhciReadl(host, CAPABILITIES2_R);
1989     }
1990 
1991     SdhciUpdateCapFlag(host, Capability1);
1992     ret = SdhciFillAdmaInfo(host);
1993     if (ret != HDF_SUCCESS) {
1994         return ret;
1995     }
1996 
1997     Capability2 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_ADMA3);
1998     Capability2 |= SDHCI_USE_SDR50_TUNING;
1999     SdhciFillClkInfo(host, Capability1, Capability2);
2000     SdhciUpdateDrvCap(host, Capability1, Capability2);
2001     ret = SdhciSystemInit(host->mmc);
2002     if (ret != HDF_SUCCESS) {
2003         return ret;
2004     }
2005 
2006     ret = OsalRegisterIrq(host->irqNum, 0, (OsalIRQHandle)SdhciIrqHandler, "MMC_IRQ", host);
2007     if (ret) {
2008         HDF_LOGE("SdhciHostInit: request irq for sdhci is err.");
2009         return HDF_FAILURE;
2010     }
2011     return HDF_SUCCESS;
2012 }
2013 
SdhciMmcBind(struct HdfDeviceObject *obj)2014 static int32_t SdhciMmcBind(struct HdfDeviceObject *obj)
2015 {
2016     struct MmcCntlr *cntlr = NULL;
2017     struct SdhciHost *host = NULL;
2018     int32_t ret;
2019 
2020     if (obj == NULL) {
2021         HDF_LOGE("SdhciMmcBind: Fail, device is NULL.");
2022         return HDF_ERR_INVALID_OBJECT;
2023     }
2024     cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr));
2025     if (cntlr == NULL) {
2026         HDF_LOGE("SdhciMmcBind: no mem for MmcCntlr.");
2027         return HDF_ERR_MALLOC_FAIL;
2028     }
2029     host = (struct SdhciHost *)OsalMemCalloc(sizeof(struct SdhciHost));
2030     if (host == NULL) {
2031         HDF_LOGE("SdhciMmcBind: no mem for SdhciHost.");
2032         OsalMemFree(cntlr);
2033         return HDF_ERR_MALLOC_FAIL;
2034     }
2035 
2036     host->mmc = cntlr;
2037     cntlr->priv = (void *)host;
2038     cntlr->ops = &g_sdhciHostOps;
2039     cntlr->hdfDevObj = obj;
2040     obj->service = &cntlr->service;
2041     /* init cntlr. */
2042     ret = MmcCntlrParse(cntlr, obj);
2043     if (ret != HDF_SUCCESS) {
2044         goto _ERR;
2045     }
2046     ret = SdhciHostParse(host, obj);
2047     if (ret != HDF_SUCCESS) {
2048         goto _ERR;
2049     }
2050     ret = SdhciHostInit(host, cntlr);
2051     if (ret != HDF_SUCCESS) {
2052         goto _ERR;
2053     }
2054     ret = MmcCntlrAdd(cntlr, true);
2055     if (ret != HDF_SUCCESS) {
2056         goto _ERR;
2057     }
2058 
2059     (void)MmcCntlrAddDetectMsgToQueue(cntlr);
2060     HDF_LOGI("%s: mmc bind success.", __func__);
2061     return HDF_SUCCESS;
2062 _ERR:
2063     SdhciDeleteHost(host);
2064     HDF_LOGE("SdhciMmcBind: fail, err = %d.", ret);
2065     return ret;
2066 }
2067 
SdhciMmcInit(struct HdfDeviceObject *obj)2068 static int32_t SdhciMmcInit(struct HdfDeviceObject *obj)
2069 {
2070     static bool procInit = false;
2071 
2072     (void)obj;
2073     if (procInit == false) {
2074         if (ProcMciInit() == HDF_SUCCESS) {
2075             procInit = true;
2076             HDF_LOGD("SdhciMmcInit: proc init success.");
2077         }
2078     }
2079     HDF_LOGI("%s: mmc init success.", __func__);
2080     return HDF_SUCCESS;
2081 }
2082 
SdhciMmcRelease(struct HdfDeviceObject *obj)2083 static void SdhciMmcRelease(struct HdfDeviceObject *obj)
2084 {
2085     struct MmcCntlr *cntlr = NULL;
2086 
2087     HDF_LOGI("%s: enter", __func__);
2088     if (obj == NULL) {
2089         return;
2090     }
2091 
2092     cntlr = (struct MmcCntlr *)obj->service;
2093     if (cntlr == NULL) {
2094         return;
2095     }
2096     SdhciDeleteHost((struct SdhciHost *)cntlr->priv);
2097 }
2098 
2099 struct HdfDriverEntry g_mmcDriverEntry = {
2100     .moduleVersion = 1,
2101     .Bind = SdhciMmcBind,
2102     .Init = SdhciMmcInit,
2103     .Release = SdhciMmcRelease,
2104     .moduleName = "hi3518_mmc_driver",
2105 };
2106 HDF_INIT(g_mmcDriverEntry);
2107