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