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", ®Base, 0);
1586 if (ret != HDF_SUCCESS) {
1587 HDF_LOGE("%s: read regBasePhy fail!", __func__);
1588 return ret;
1589 }
1590 ret = drsOps->GetUint32(node, "regSize", ®Size, 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