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