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 "himci.h"
17 #include "himci_proc.h"
18
19 #define HDF_LOG_TAG himci_adapter
20
21 #define HIMCI_PIN_NUM 6
22 #define HIMCI_VOLT_SWITCH_TIMEOUT 10
23 #define HIMCI_PHASE_DLL_START_ELEMENT 2
24
HimciDumpRegs(struct HimciHost * host)25 static void HimciDumpRegs(struct HimciHost *host)
26 {
27 HDF_LOGE(": =========== DUMP (host%u) REGISTER===========", host->id);
28 HDF_LOGE(": CTRL : 0x%08x | PWREN: 0x%04x",
29 HIMCI_READL((uintptr_t)host->base + MMC_CTRL), HIMCI_READL((uintptr_t)host->base + MMC_PWREN));
30 HDF_LOGE(": CLKDIV : 0x%08x | CLKENA: 0x%04x",
31 HIMCI_READL((uintptr_t)host->base + MMC_CLKDIV), HIMCI_READL((uintptr_t)host->base + MMC_CLKENA));
32 HDF_LOGE(": TMOUT : 0x%08x | CTYPE: 0x%04x",
33 HIMCI_READL((uintptr_t)host->base + MMC_TMOUT), HIMCI_READL((uintptr_t)host->base + MMC_CTYPE));
34 HDF_LOGE(": BLKSIZ : 0x%08x | BYTCNT: 0x%04x",
35 HIMCI_READL((uintptr_t)host->base + MMC_BLKSIZ), HIMCI_READL((uintptr_t)host->base + MMC_BYTCNT));
36 HDF_LOGE(": CMD : 0x%08x | CMDARG: 0x%04x",
37 HIMCI_READL((uintptr_t)host->base + MMC_CMD), HIMCI_READL((uintptr_t)host->base + MMC_CMDARG));
38 HDF_LOGE(": RESP0 : 0x%08x | RESP1: 0x%04x",
39 HIMCI_READL((uintptr_t)host->base + MMC_RESP0), HIMCI_READL((uintptr_t)host->base + MMC_RESP1));
40 HDF_LOGE(": RESP2 : 0x%08x | RESP3: 0x%04x",
41 HIMCI_READL((uintptr_t)host->base + MMC_RESP2), HIMCI_READL((uintptr_t)host->base + MMC_RESP3));
42 HDF_LOGE(": RINTSTS : 0x%08x | STATUS: 0x%04x",
43 HIMCI_READL((uintptr_t)host->base + MMC_RINTSTS), HIMCI_READL((uintptr_t)host->base + MMC_STATUS));
44 HDF_LOGE(": BMOD : 0x%08x | IDSTS: 0x%04x",
45 HIMCI_READL((uintptr_t)host->base + MMC_BMOD), HIMCI_READL((uintptr_t)host->base + MMC_IDSTS));
46 HDF_LOGE(": IDINTEN : 0x%08x | CARDTHRCTL : 0x%08x",
47 HIMCI_READL((uintptr_t)host->base + MMC_IDINTEN), HIMCI_READL((uintptr_t)host->base + MMC_CARDTHRCTL));
48 HDF_LOGE(": DDR_REG: 0x%04x | ENABLE_SHIFT : 0x%08x",
49 HIMCI_READL((uintptr_t)host->base + MMC_EMMC_DDR_REG), HIMCI_READL((uintptr_t)host->base + MMC_ENABLE_SHIFT));
50 HDF_LOGE(": =============================================");
51 }
52
HimciSetEmmcDrvCap(struct MmcCntlr * cntlr)53 static void HimciSetEmmcDrvCap(struct MmcCntlr *cntlr)
54 {
55 uint32_t i, j, val;
56 uint32_t *pinDrvCap = NULL;
57 /* clk cmd data0 data1 data2 data3 */
58 uint32_t emmcHs200Drv[] = { 0x2b0, 0x1c0, 0x1c0, 0x1c0, 0x1c0, 0x1c0 };
59 uint32_t emmcHsDrv[] = { 0x6b0, 0x5e0, 0x5e0, 0x5e0, 0x5e0, 0x5e0 };
60 uint32_t emmcDsDrv[] = { 0x6b0, 0x5f0, 0x5f0, 0x5f0, 0x5f0, 0x5f0 };
61 uint32_t emmcDs400kDrv[] = { 0x6c0, 0x5f0, 0x5f0, 0x5f0, 0x5f0, 0x5f0 };
62
63 if (cntlr->curDev->workPara.timing == BUS_TIMING_MMC_HS200) {
64 pinDrvCap = emmcHs200Drv;
65 } else if (cntlr->curDev->workPara.timing == BUS_TIMING_MMC_HS) {
66 pinDrvCap = emmcHsDrv;
67 } else {
68 if (cntlr->curDev->workPara.clock == 400000) {
69 pinDrvCap = emmcDs400kDrv;
70 } else {
71 pinDrvCap = emmcDsDrv;
72 }
73 }
74
75 for (i = REG_CTRL_EMMC_START, j = 0; j < HIMCI_PIN_NUM; i = i + REG_CTRL_NUM, j++) {
76 val = HIMCI_READL(i);
77 /*
78 * [10]:SR
79 * [9]:internel pull down
80 * [8]:internel pull up
81 */
82 val = val & (~(0x7f0));
83 val |= pinDrvCap[j];
84 HIMCI_WRITEL(val, i);
85 }
86 }
87
HimciSetSdDrvCap(struct MmcCntlr * cntlr)88 static void HimciSetSdDrvCap(struct MmcCntlr *cntlr)
89 {
90 uint32_t i, j, val;
91 uint32_t *pinDrvCap = NULL;
92 /* clk cmd data0 data1 data2 data3 */
93 uint32_t sdSdr104Drv[] = { 0x290, 0x1c0, 0x1c0, 0x1c0, 0x1c0, 0x1c0 };
94 uint32_t sdSdr50Drv[] = { 0x290, 0x1c0, 0x1c0, 0x1c0, 0x1c0, 0x1c0 };
95 uint32_t sdSdr25Drv[] = { 0x6b0, 0x5d0, 0x5d0, 0x5d0, 0x5d0, 0x5d0 };
96 uint32_t sdSdr12Drv[] = { 0x6b0, 0x5e0, 0x5e0, 0x5e0, 0x5e0, 0x5e0 };
97 uint32_t sdHsDrv[] = { 0x6d0, 0x5f0, 0x5f0, 0x5f0, 0x5f0, 0x5f0 };
98 uint32_t sdDsDrv[] = { 0x6b0, 0x5e0, 0x5e0, 0x5e0, 0x5e0, 0x5e0 };
99
100 if (cntlr->curDev->workPara.timing == BUS_TIMING_UHS_SDR104) {
101 pinDrvCap = sdSdr104Drv;
102 } else if (cntlr->curDev->workPara.timing == BUS_TIMING_UHS_SDR50) {
103 pinDrvCap = sdSdr50Drv;
104 } else if (cntlr->curDev->workPara.timing == BUS_TIMING_UHS_SDR25) {
105 pinDrvCap = sdSdr25Drv;
106 } else if (cntlr->curDev->workPara.timing == BUS_TIMING_UHS_SDR12) {
107 pinDrvCap = sdSdr12Drv;
108 } else if (cntlr->curDev->workPara.timing == BUS_TIMING_SD_HS) {
109 pinDrvCap = sdHsDrv;
110 } else {
111 pinDrvCap = sdDsDrv;
112 }
113
114 for (i = REG_CTRL_SD_START, j = 0; j < HIMCI_PIN_NUM; i = i + REG_CTRL_NUM, j++) {
115 val = HIMCI_READL(i);
116 /*
117 * [10]:SR
118 * [9]:internel pull down
119 * [8]:internel pull up
120 */
121 val = val & (~(0x7f0));
122 val |= pinDrvCap[j];
123 HIMCI_WRITEL(val, i);
124 }
125 }
126
HimciSetSdioDrvCap(struct MmcCntlr * cntlr)127 static void HimciSetSdioDrvCap(struct MmcCntlr *cntlr)
128 {
129 uint32_t i, j, val;
130 uint32_t *pinDrvCap = NULL;
131 /* clk cmd data0 data1 data2 data3 */
132 uint32_t sdioSdr104Drv[] = { 0x290, 0x1c0, 0x1c0, 0x1c0, 0x1c0, 0x1c0 };
133 uint32_t sdioSdr50Drv[] = { 0x290, 0x1c0, 0x1c0, 0x1c0, 0x1c0, 0x1c0 };
134 uint32_t sdioSdr25Drv[] = { 0x6b0, 0x5d0, 0x5d0, 0x5d0, 0x5d0, 0x5d0 };
135 uint32_t sdioSdr12Drv[] = { 0x6b0, 0x5e0, 0x5e0, 0x5e0, 0x5e0, 0x5e0 };
136 uint32_t sdioHsDrv[] = { 0x6d0, 0x5f0, 0x5f0, 0x5f0, 0x5f0, 0x5f0 };
137 uint32_t sdioDsDrv[] = { 0x6b0, 0x5e0, 0x5e0, 0x5e0, 0x5e0, 0x5e0 };
138
139 if (cntlr->curDev->workPara.timing == BUS_TIMING_UHS_SDR104) {
140 pinDrvCap = sdioSdr104Drv;
141 } else if (cntlr->curDev->workPara.timing == BUS_TIMING_UHS_SDR50) {
142 pinDrvCap = sdioSdr50Drv;
143 } else if (cntlr->curDev->workPara.timing == BUS_TIMING_UHS_SDR25) {
144 pinDrvCap = sdioSdr25Drv;
145 } else if (cntlr->curDev->workPara.timing == BUS_TIMING_UHS_SDR12) {
146 pinDrvCap = sdioSdr12Drv;
147 } else if (cntlr->curDev->workPara.timing == BUS_TIMING_SD_HS) {
148 pinDrvCap = sdioHsDrv;
149 } else {
150 pinDrvCap = sdioDsDrv;
151 }
152
153 for (i = REG_CTRL_SDIO_START, j = 0; j < HIMCI_PIN_NUM; i = i + REG_CTRL_NUM, j++) {
154 val = HIMCI_READL(i);
155 /*
156 * [10]:SR
157 * [9]:internel pull down
158 * [8]:internel pull up
159 */
160 val = val & (~(0x7f0));
161 val |= pinDrvCap[j];
162 HIMCI_WRITEL(val, i);
163 }
164 }
165
HimciSetDrvCap(struct MmcCntlr * cntlr)166 static void HimciSetDrvCap(struct MmcCntlr *cntlr)
167 {
168 if (cntlr == NULL) {
169 return;
170 }
171
172 if (cntlr->devType == MMC_DEV_EMMC) {
173 HimciSetEmmcDrvCap(cntlr);
174 } else if (cntlr->devType == MMC_DEV_SD) {
175 HimciSetSdDrvCap(cntlr);
176 } else {
177 HimciSetSdioDrvCap(cntlr);
178 }
179 }
180
HimciClkDiv(struct HimciHost * host,uint32_t clock)181 static uint32_t HimciClkDiv(struct HimciHost *host, uint32_t clock)
182 {
183 uint32_t clkDiv = 0;
184 uint32_t val, hostClk, debounce;
185 uint32_t regs[] = { PERI_CRG82, PERI_CRG88, PERI_CRG85 };
186
187 val = HIMCI_READL(regs[host->id]);
188 val &= ~(HIMCI_CLK_SEL_MASK);
189 if (clock >= HIMCI_MMC_FREQ_150M) {
190 hostClk = HIMCI_MMC_FREQ_150M;
191 debounce = DEBOUNCE_E;
192 } else if (clock >= HIMCI_MMC_FREQ_100M) {
193 hostClk = HIMCI_MMC_FREQ_100M;
194 val |= HIMCI_CLK_SEL_100M;
195 debounce = DEBOUNCE_H;
196 } else if (clock >= HIMCI_MMC_FREQ_50M) {
197 hostClk = HIMCI_MMC_FREQ_50M;
198 val |= HIMCI_CLK_SEL_50M;
199 debounce = DEBOUNCE_M;
200 } else if (clock >= HIMCI_MMC_FREQ_25M) {
201 hostClk = HIMCI_MMC_FREQ_25M;
202 val |= HIMCI_CLK_SEL_25M;
203 debounce = DEBOUNCE_L;
204 } else {
205 if (clock > (HIMCI_MMC_FREQ_150M / CLK_DIVIDER)) {
206 hostClk = HIMCI_MMC_FREQ_150M;
207 debounce = DEBOUNCE_E;
208 } else if (clock > (HIMCI_MMC_FREQ_100M / CLK_DIVIDER)) {
209 val |= HIMCI_CLK_SEL_100M;
210 hostClk = HIMCI_MMC_FREQ_100M;
211 debounce = DEBOUNCE_H;
212 } else if (clock > (HIMCI_MMC_FREQ_50M / CLK_DIVIDER)) {
213 val |= HIMCI_CLK_SEL_50M;
214 hostClk = HIMCI_MMC_FREQ_50M;
215 debounce = DEBOUNCE_M;
216 } else {
217 val |= HIMCI_CLK_SEL_25M;
218 hostClk = HIMCI_MMC_FREQ_25M;
219 debounce = DEBOUNCE_L;
220 }
221 clkDiv = hostClk / (clock * 2);
222 if (hostClk % (clock * 2) > 0) {
223 clkDiv++;
224 }
225 if (clkDiv > MAX_CLKDIV_VAL) {
226 clkDiv = MAX_CLKDIV_VAL;
227 }
228 }
229 HIMCI_WRITEL(debounce, (uintptr_t)host->base + MMC_DEBNCE);
230 HIMCI_WRITEL(val, regs[host->id]);
231 HIMCI_WRITEL(clkDiv, (uintptr_t)host->base + MMC_CLKDIV);
232
233 return hostClk;
234 }
235
HimciDmaReset(struct HimciHost * host)236 static void HimciDmaReset(struct HimciHost *host)
237 {
238 uint32_t val;
239
240 val = HIMCI_READL((uintptr_t)host->base + MMC_BMOD);
241 val |= BMOD_SWR;
242 HIMCI_WRITEL(val, (uintptr_t)host->base + MMC_BMOD);
243
244 val = HIMCI_READL((uintptr_t)host->base + MMC_CTRL);
245 val |= CTRL_RESET | FIFO_RESET | DMA_RESET;
246 HIMCI_WRITEL(val, (uintptr_t)host->base + MMC_CTRL);
247
248 OsalUDelay(1);
249 HIMCI_WRITEL(ALL_INT_CLR, (uintptr_t)host->base + MMC_RINTSTS);
250 }
251
HimciDmaStart(struct HimciHost * host)252 static void HimciDmaStart(struct HimciHost *host)
253 {
254 uint32_t val;
255
256 HIMCI_WRITEL(host->dmaPaddr, (uintptr_t)host->base + MMC_DBADDR);
257 val = HIMCI_READL((uintptr_t)host->base + MMC_BMOD);
258 val |= BMOD_DMA_EN;
259 HIMCI_WRITEL(val, (uintptr_t)host->base + MMC_BMOD);
260 }
261
HimciDmaStop(struct HimciHost * host)262 static void HimciDmaStop(struct HimciHost *host)
263 {
264 uint32_t val;
265
266 val = HIMCI_READL((uintptr_t)host->base + MMC_BMOD);
267 val &= (~BMOD_DMA_EN);
268 HIMCI_WRITEL(val, (uintptr_t)host->base + MMC_BMOD);
269 }
270
HimciDmaCacheClean(void * addr,uint32_t size)271 static void HimciDmaCacheClean(void *addr, uint32_t size)
272 {
273 addr = (void *)(uintptr_t)DMA_TO_VMM_ADDR((paddr_t)(uintptr_t)addr);
274 uint32_t start = (uintptr_t)addr & ~(CACHE_ALIGNED_SIZE - 1);
275 uint32_t end = (uintptr_t)addr + size;
276
277 end = ALIGN(end, CACHE_ALIGNED_SIZE);
278 DCacheFlushRange(start, end);
279 }
280
HimciDmaCacheInv(void * addr,uint32_t size)281 static void HimciDmaCacheInv(void *addr, uint32_t size)
282 {
283 addr = (void *)(uintptr_t)DMA_TO_VMM_ADDR((paddr_t)(uintptr_t)addr);
284 uint32_t start = (uintptr_t)addr & ~(CACHE_ALIGNED_SIZE - 1);
285 uint32_t end = (uintptr_t)addr + size;
286
287 end = ALIGN(end, CACHE_ALIGNED_SIZE);
288 DCacheInvRange(start, end);
289 }
290
HimciIsMultiBlock(struct MmcCmd * cmd)291 static bool HimciIsMultiBlock(struct MmcCmd *cmd)
292 {
293 if (cmd->cmdCode == WRITE_MULTIPLE_BLOCK || cmd->cmdCode == READ_MULTIPLE_BLOCK) {
294 return true;
295 }
296 if (cmd->data->blockNum > 1) {
297 return true;
298 }
299 return false;
300 }
301
HimciNeedAutoStop(struct MmcCntlr * cntlr)302 static bool HimciNeedAutoStop(struct MmcCntlr *cntlr)
303 {
304 if (cntlr->curDev->type == MMC_DEV_SDIO) {
305 return false;
306 }
307
308 if (((cntlr->curDev->type == MMC_DEV_SD || cntlr->curDev->type == MMC_DEV_COMBO) &&
309 MmcCntlrSdSupportCmd23(cntlr) == false) ||
310 (cntlr->curDev->type == MMC_DEV_EMMC && MmcCntlrEmmcSupportCmd23(cntlr) == false)) {
311 return true;
312 }
313 if (cntlr->caps.bits.cmd23 > 0) {
314 /* both host and device support cmd23. */
315 return false;
316 }
317
318 /* the device support cmd23 but host doesn't support cmd23 */
319 return true;
320 }
321
HimciFillCmdReg(union HimciCmdRegArg * reg,struct MmcCmd * cmd)322 static int32_t HimciFillCmdReg(union HimciCmdRegArg *reg, struct MmcCmd *cmd)
323 {
324 if (cmd->cmdCode == STOP_TRANSMISSION) {
325 reg->bits.stopAbortCmd = 1;
326 reg->bits.waitDataComplete = 0;
327 } else {
328 reg->bits.stopAbortCmd = 0;
329 reg->bits.waitDataComplete = 1;
330 }
331
332 switch (MMC_RESP_TYPE(cmd)) {
333 case MMC_RESP_NONE:
334 reg->bits.rspExpect = 0;
335 reg->bits.rspLen = 0;
336 reg->bits.checkRspCrc = 0;
337 break;
338 case MMC_RESP_R1:
339 case MMC_RESP_R1B:
340 reg->bits.rspExpect = 1;
341 reg->bits.rspLen = 0;
342 reg->bits.checkRspCrc = 1;
343 break;
344 case MMC_RESP_R2:
345 reg->bits.rspExpect = 1;
346 reg->bits.rspLen = 1;
347 reg->bits.checkRspCrc = 1;
348 break;
349 case MMC_RESP_R3:
350 case MMC_RESP_R1 & (~RESP_CRC):
351 reg->bits.rspExpect = 1;
352 reg->bits.rspLen = 0;
353 reg->bits.checkRspCrc = 0;
354 break;
355 default:
356 cmd->returnError = HDF_ERR_INVALID_PARAM;
357 HDF_LOGE("unhandled response type 0x%x", MMC_RESP_TYPE(cmd));
358 return HDF_ERR_INVALID_PARAM;
359 }
360
361 reg->bits.sendInitialization = 0;
362 if (cmd->cmdCode == GO_IDLE_STATE) {
363 reg->bits.sendInitialization = 1;
364 }
365 /* CMD 11 check switch voltage */
366 reg->bits.voltSwitch = 0;
367 if (cmd->cmdCode == SD_CMD_SWITCH_VOLTAGE) {
368 reg->bits.voltSwitch = 1;
369 }
370
371 reg->bits.cardNumber = 0;
372 reg->bits.cmdIndex = cmd->cmdCode;
373 reg->bits.startCmd = 1;
374 reg->bits.updateClkRegOnly = 0;
375 return HDF_SUCCESS;
376 }
377
HimciUpdateCmdReg(union HimciCmdRegArg * reg,struct HimciHost * host)378 static int32_t HimciUpdateCmdReg(union HimciCmdRegArg *reg, struct HimciHost *host)
379 {
380 struct MmcCmd *cmd = host->cmd;
381 struct MmcData *data = cmd->data;
382
383 if (data != NULL) {
384 reg->bits.dataTransferExpected = 1;
385 if ((data->dataFlags & (DATA_WRITE | DATA_READ)) > 0) {
386 reg->bits.transferMode = 0;
387 }
388 if ((data->dataFlags & DATA_STREAM) > 0) {
389 reg->bits.transferMode = 1;
390 }
391 if ((data->dataFlags & DATA_WRITE) > 0) {
392 reg->bits.readWrite = 1;
393 } else if ((data->dataFlags & DATA_READ) > 0) {
394 reg->bits.readWrite = 0;
395 }
396 reg->bits.sendAutoStop = 0;
397 if (HimciIsMultiBlock(cmd) == true && HimciNeedAutoStop(host->mmc) == true) {
398 reg->bits.sendAutoStop = 1;
399 }
400 } else {
401 reg->bits.dataTransferExpected = 0;
402 reg->bits.transferMode = 0;
403 reg->bits.readWrite = 0;
404 }
405
406 if (HimciFillCmdReg(reg, cmd) != HDF_SUCCESS) {
407 return HDF_FAILURE;
408 }
409 return HDF_SUCCESS;
410 }
411
HimciExecCmd(struct HimciHost * host)412 static int32_t HimciExecCmd(struct HimciHost *host)
413 {
414 union HimciCmdRegArg cmdRegs;
415 int32_t ret;
416 struct MmcCmd *cmd = host->cmd;
417
418 HIMCI_WRITEL(cmd->argument, (uintptr_t)host->base + MMC_CMDARG);
419 cmdRegs.arg = HIMCI_READL((uintptr_t)host->base + MMC_CMD);
420 ret = HimciUpdateCmdReg(&cmdRegs, host);
421 if (ret != HDF_SUCCESS) {
422 return ret;
423 }
424 HIMCI_WRITEL(cmdRegs.arg, (uintptr_t)host->base + MMC_CMD);
425 return HDF_SUCCESS;
426 }
427
HimciWaitCmd(struct HimciHost * host)428 static int32_t HimciWaitCmd(struct HimciHost *host)
429 {
430 int32_t reties = 0;
431 uint32_t val;
432 unsigned long flags = 0;
433
434 while (true) {
435 /*
436 * Check if CMD start_cmd bit is clear.
437 * start_cmd = 0 means MMC Host controller has loaded registers and next command can be loaded in.
438 */
439 val = HIMCI_READL((uintptr_t)host->base + MMC_CMD);
440 if ((val & START_CMD) == 0) {
441 break;
442 }
443 /* Check if Raw_Intr_Status HLE bit is set. */
444 HIMCI_IRQ_LOCK(&flags);
445 val = HIMCI_READL((uintptr_t)host->base + MMC_RINTSTS);
446 if ((val & HLE_INT_STATUS) > 0) {
447 val |= HLE_INT_STATUS;
448 HIMCI_WRITEL(val, (uintptr_t)host->base + MMC_RINTSTS);
449 HIMCI_IRQ_UNLOCK(flags);
450 HDF_LOGE("host%u: Other CMD is running! please operate cmd again!", host->id);
451 return HDF_MMC_ERR_OTHER_CMD_IS_RUNNING;
452 }
453 HIMCI_IRQ_UNLOCK(flags);
454 OsalUDelay(100);
455
456 /* Check if number of retries for this are over. */
457 reties++;
458 if (reties >= HIMCI_MAX_RETRY_COUNT) {
459 if (host->cmd != NULL) {
460 HDF_LOGE("wait cmd[%u] complete is timeout!", host->cmd->cmdCode);
461 } else {
462 HDF_LOGE("timeout!");
463 }
464 return HDF_FAILURE;
465 }
466 }
467 return HDF_SUCCESS;
468 }
469
HimciCmdDone(struct HimciHost * host)470 static void HimciCmdDone(struct HimciHost *host)
471 {
472 uint32_t i;
473 struct MmcCmd *cmd = host->cmd;
474
475 if ((cmd->respType & RESP_PRESENT) == 0) {
476 return;
477 }
478
479 if (MMC_RESP_TYPE(cmd) != MMC_RESP_R2) {
480 cmd->resp[0] = HIMCI_READL((uintptr_t)host->base + MMC_RESP0);
481 return;
482 }
483
484 for (i = 0; i < MMC_CMD_RESP_SIZE; i++) {
485 cmd->resp[i] = HIMCI_READL((uintptr_t)host->base + MMC_RESP3 - i * 0x4);
486 /* R2 must delay some time here when use UHI card. */
487 OsalUDelay(1000);
488 }
489 }
490
HimciDataSync(struct HimciHost * host,struct MmcData * data)491 static void HimciDataSync(struct HimciHost *host, struct MmcData *data)
492 {
493 uint32_t sgPhyAddr, sgLength, i;
494
495 if ((data->dataFlags & DATA_READ) > 0) {
496 for (i = 0; i < host->dmaSgNum; i++) {
497 sgLength = HIMCI_SG_DMA_LEN(&host->sg[i]);
498 sgPhyAddr = HIMCI_SG_DMA_ADDRESS(&host->sg[i]);
499 HimciDmaCacheInv((void *)(uintptr_t)sgPhyAddr, sgLength);
500 }
501 }
502 }
503
HimciDataDone(struct HimciHost * host,uint32_t state)504 static void HimciDataDone(struct HimciHost *host, uint32_t state)
505 {
506 struct MmcData *data = NULL;
507
508 if (host->cmd == NULL) {
509 return;
510 }
511 if (host->cmd->data == NULL) {
512 return;
513 }
514
515 data = host->cmd->data;
516 if ((state & (HTO_INT_STATUS | DRTO_INT_STATUS | RTO_INT_STATUS)) > 0) {
517 data->returnError = HDF_ERR_TIMEOUT;
518 } else if ((state & (EBE_INT_STATUS | SBE_INT_STATUS | FRUN_INT_STATUS | DCRC_INT_STATUS)) > 0) {
519 data->returnError = HDF_MMC_ERR_ILLEGAL_SEQ;
520 }
521 }
522
HimciWaitCmdComplete(struct HimciHost * host)523 static void HimciWaitCmdComplete(struct HimciHost *host)
524 {
525 struct MmcCmd *cmd = host->cmd;
526 uint32_t timeout, status;
527 unsigned long flags = 0;
528
529 if (host->isTuning == true) {
530 timeout = HIMCI_TUNINT_REQ_TIMEOUT;
531 } else {
532 timeout = HIMCI_REQUEST_TIMEOUT;
533 }
534
535 HIMCI_IRQ_LOCK(&flags);
536 host->waitForEvent = true;
537 HIMCI_IRQ_UNLOCK(flags);
538
539 status = HIMCI_EVENT_WAIT(&host->himciEvent, (HIMCI_PEND_DTO_M | HIMCI_PEND_ACCIDENT), timeout);
540 if (status == LOS_ERRNO_EVENT_READ_TIMEOUT || status == HIMCI_PEND_ACCIDENT) {
541 if (status == HIMCI_PEND_ACCIDENT) {
542 cmd->returnError = HDF_ERR_IO;
543 } else {
544 cmd->returnError = HDF_ERR_TIMEOUT;
545 if (host->isTuning == false) {
546 HimciDumpRegs(host);
547 HDF_LOGE("host%u cmd%u(arg 0x%x) timeout!", host->id, cmd->cmdCode, cmd->argument);
548 }
549 }
550 if (host->cmd->data != NULL) {
551 HimciDmaStop(host);
552 HimciDataDone(host, 0);
553 }
554 } else if (host->cmd->data != NULL) {
555 HimciDataSync(host, host->cmd->data);
556 }
557
558 HIMCI_IRQ_LOCK(&flags);
559 host->waitForEvent = false;
560 HIMCI_IRQ_UNLOCK(flags);
561 HimciCmdDone(host);
562 }
563
HimciCardPlugged(struct MmcCntlr * cntlr)564 static bool HimciCardPlugged(struct MmcCntlr *cntlr)
565 {
566 unsigned int status;
567 struct HimciHost *host = NULL;
568
569 if ((cntlr == NULL) || (cntlr->priv == NULL)) {
570 return false;
571 }
572
573 if (cntlr->devType == MMC_DEV_SDIO || cntlr->devType == MMC_DEV_EMMC) {
574 return true;
575 }
576
577 host = (struct HimciHost *)cntlr->priv;
578 status = HIMCI_READL((uintptr_t)host->base + MMC_CDETECT);
579 if ((status & CARD_UNPLUGED) == 0) {
580 return true;
581 }
582 return false;
583 }
584
HimciSendCmd23(struct HimciHost * host,uint32_t blockNum)585 static int32_t HimciSendCmd23(struct HimciHost *host, uint32_t blockNum)
586 {
587 int32_t ret;
588 struct MmcCmd cmd = {0};
589
590 cmd.cmdCode = SET_BLOCK_COUNT;
591 cmd.argument = blockNum;
592 host->cmd = &cmd;
593 ret = HimciExecCmd(host);
594 if (ret != HDF_SUCCESS) {
595 host->cmd = NULL;
596 HDF_LOGE("cmd23 failed, ret = %d!", ret);
597 return ret;
598 }
599
600 HimciWaitCmdComplete(host);
601 host->cmd = NULL;
602 return cmd.returnError;
603 }
604
HimciFifoReset(struct HimciHost * host)605 static int32_t HimciFifoReset(struct HimciHost *host)
606 {
607 uint32_t i;
608
609 HIMCI_SETL(host, MMC_CTRL, FIFO_RESET);
610 for (i = 0; i < HIMCI_MAX_RETRY_COUNT; i++) {
611 if ((HIMCI_READL((uintptr_t)host->base + MMC_CTRL) & FIFO_RESET) == 0) {
612 return HDF_SUCCESS;
613 }
614 }
615 return HDF_ERR_TIMEOUT;
616 }
617
HimciFillDmaSg(struct HimciHost * host,struct MmcData * data)618 static int32_t HimciFillDmaSg(struct HimciHost *host, struct MmcData *data)
619 {
620 uint32_t len = data->blockNum * data->blockSize;
621 int32_t ret;
622
623 if (len == 0) {
624 return HDF_ERR_INVALID_PARAM;
625 }
626
627 if (data->scatter != NULL && data->dataBuffer == NULL) {
628 host->sg = data->scatter;
629 host->dmaSgNum = data->scatterLen;
630 return HDF_SUCCESS;
631 }
632 if (data->dataBuffer == NULL) {
633 return HDF_ERR_INVALID_PARAM;
634 }
635
636 host->alignedBuff = (uint8_t *)OsalMemAllocAlign(CACHE_ALIGNED_SIZE, ALIGN(len, CACHE_ALIGNED_SIZE));
637 if (host->alignedBuff == NULL) {
638 HDF_LOGE("HimciFillDmaSg: alloc fail.");
639 return HDF_ERR_MALLOC_FAIL;
640 }
641
642 ret = memcpy_s(host->alignedBuff, len, data->dataBuffer, len);
643 if (ret != EOK) {
644 HDF_LOGE("memcpy_s fail ret = %d.", ret);
645 OsalMemFree(host->alignedBuff);
646 host->alignedBuff = NULL;
647 return HDF_FAILURE;
648 }
649 host->buffLen = len;
650 sg_init_one(&host->dmaSg, (const void *)host->alignedBuff, len);
651 host->dmaSgNum = 1;
652 host->sg = &host->dmaSg;
653 return HDF_SUCCESS;
654 }
655
HimciClearDmaSg(struct HimciHost * host,struct MmcData * data)656 static void HimciClearDmaSg(struct HimciHost *host, struct MmcData *data)
657 {
658 uint32_t len;
659
660 if (data == NULL) {
661 return;
662 }
663
664 len = data->blockNum * data->blockSize;
665 if (host->alignedBuff != NULL && data->dataBuffer != NULL && len > 0 && host->buffLen > 0) {
666 if ((data->dataFlags & DATA_READ) > 0) {
667 if (memcpy_s(data->dataBuffer, len, host->alignedBuff, host->buffLen) != EOK) {
668 HDF_LOGE("%s: memcpy_s failed!", __func__);
669 }
670 }
671 }
672 if (host->alignedBuff != NULL) {
673 OsalMemFree(host->alignedBuff);
674 host->alignedBuff = NULL;
675 }
676 host->dmaSgNum = 0;
677 host->buffLen = 0;
678 host->sg = NULL;
679 }
680
HimciSetupData(struct HimciHost * host,struct MmcData * data)681 static int32_t HimciSetupData(struct HimciHost *host, struct MmcData *data)
682 {
683 int32_t ret;
684 uint32_t sgPhyAddr, sgLength, i;
685 uint32_t desCnt = 0;
686 uint32_t maximum = HIMCI_PAGE_SIZE / sizeof(struct HimciDes);
687 struct HimciDes *des = NULL;
688 uint32_t dmaDir = DMA_TO_DEVICE;
689
690 if ((data->dataFlags & DATA_READ) > 0) {
691 dmaDir = DMA_FROM_DEVICE;
692 }
693
694 des = (struct HimciDes *)host->dmaVaddr;
695 for (i = 0; (i < host->dmaSgNum) && (desCnt < maximum); i++) {
696 sgLength = HIMCI_SG_DMA_LEN(&host->sg[i]);
697 sgPhyAddr = HIMCI_SG_DMA_ADDRESS(&host->sg[i]);
698 if ((sgPhyAddr & (CACHE_ALIGNED_SIZE - 1)) != 0) {
699 HDF_LOGE("host%u:sg_phyaddr:0x%x sg_length:0x%x.", host->id, sgPhyAddr, sgLength);
700 return HDF_FAILURE;
701 }
702 if (dmaDir == DMA_TO_DEVICE) {
703 HimciDmaCacheClean((void *)(uintptr_t)sgPhyAddr, sgLength);
704 } else {
705 HimciDmaCacheInv((void *)(uintptr_t)sgPhyAddr, sgLength);
706 }
707 while (sgLength && (desCnt < maximum)) {
708 des[desCnt].dmaDesCtrl = DMA_DES_OWN | DMA_DES_NEXT_DES;
709 des[desCnt].dmaDesBufAddr = sgPhyAddr;
710 /* idmac_des_next_addr is paddr for dma */
711 des[desCnt].dmaDesNextAddr = host->dmaPaddr + (desCnt + 1) * sizeof(struct HimciDes);
712 if (sgLength >= HIMCI_DMA_MAX_BUFF_SIZE) {
713 des[desCnt].dmaDesBufSize = HIMCI_DMA_MAX_BUFF_SIZE;
714 sgLength -= HIMCI_DMA_MAX_BUFF_SIZE;
715 sgPhyAddr += HIMCI_DMA_MAX_BUFF_SIZE;
716 } else {
717 /* data alignment */
718 des[desCnt].dmaDesBufSize = sgLength;
719 sgLength = 0;
720 }
721 desCnt++;
722 }
723 }
724 des[0].dmaDesCtrl |= DMA_DES_FIRST_DES;
725 des[desCnt - 1].dmaDesCtrl |= DMA_DES_LAST_DES;
726 des[desCnt - 1].dmaDesNextAddr = 0;
727
728 HimciDmaCacheClean((void *)(uintptr_t)host->dmaPaddr, HIMCI_PAGE_SIZE);
729
730 desCnt = data->blockSize * data->blockNum;
731 HIMCI_WRITEL(desCnt, (uintptr_t)host->base + MMC_BYTCNT);
732 HIMCI_WRITEL(data->blockSize, (uintptr_t)host->base + MMC_BLKSIZ);
733
734 ret = HimciFifoReset(host);
735 if (ret != HDF_SUCCESS) {
736 return ret;
737 }
738 HimciDmaStart(host);
739 return HDF_SUCCESS;
740 }
741
HimciWaitCardComplete(struct HimciHost * host)742 static bool HimciWaitCardComplete(struct HimciHost *host)
743 {
744 uint64_t timeout;
745 uint32_t cycle, busy;
746
747 timeout = LOS_TickCountGet() + HIMCI_CARD_COMPLETE_TIMEOUT;
748 do {
749 for (cycle = 0; cycle < HIMCI_MAX_RETRY_COUNT; cycle++) {
750 busy = HIMCI_READL((uintptr_t)host->base + MMC_STATUS);
751 if ((busy & DATA_BUSY) == 0) {
752 return true;
753 }
754 }
755 if (HimciCardPlugged(host->mmc) == false) {
756 HDF_LOGE("card is unplugged.");
757 return false;
758 }
759 LOS_Schedule();
760 } while (LOS_TickCountGet() < timeout);
761
762 return false;
763 }
764
HimciCmdDatePrepare(struct MmcCntlr * cntlr,struct MmcCmd * cmd,struct HimciHost * host)765 static int32_t HimciCmdDatePrepare(struct MmcCntlr *cntlr, struct MmcCmd *cmd, struct HimciHost *host)
766 {
767 int32_t ret;
768 host->cmd = cmd;
769 if (cmd->data != NULL) {
770 if (HimciIsMultiBlock(cmd) == true && HimciNeedAutoStop(cntlr) == false) {
771 ret = HimciSendCmd23(host, cmd->data->blockNum);
772 if (ret != HDF_SUCCESS) {
773 cmd->returnError = ret;
774 return ret;
775 }
776 }
777 host->cmd = cmd;
778 ret = HimciFillDmaSg(host, cmd->data);
779 if (ret != HDF_SUCCESS) {
780 return ret;
781 }
782 ret = HimciSetupData(host, cmd->data);
783 if (ret != HDF_SUCCESS) {
784 cmd->data->returnError = ret;
785 HDF_LOGE("setup data fail, err = %d.", ret);
786 return ret;
787 }
788 } else {
789 HIMCI_WRITEL(0, (uintptr_t)host->base + MMC_BYTCNT);
790 HIMCI_WRITEL(0, (uintptr_t)host->base + MMC_BLKSIZ);
791 }
792 return HDF_SUCCESS;
793 }
794
HimciDoRequest(struct MmcCntlr * cntlr,struct MmcCmd * cmd)795 static int32_t HimciDoRequest(struct MmcCntlr *cntlr, struct MmcCmd *cmd)
796 {
797 struct HimciHost *host = NULL;
798 int32_t ret = HDF_SUCCESS;
799
800 if ((cntlr == NULL) || (cntlr->priv == NULL) || (cmd == NULL)) {
801 return HDF_ERR_INVALID_OBJECT;
802 }
803
804 host = (struct HimciHost *)cntlr->priv;
805 (void)OsalMutexLock(&host->mutex);
806 if (HimciCardPlugged(cntlr) == false) {
807 cmd->returnError = HDF_PLT_ERR_NO_DEV;
808 goto _END;
809 }
810
811 if (HimciWaitCardComplete(host) == false) {
812 HDF_LOGE("card is busy, can not send cmd.");
813 cmd->returnError = HDF_ERR_TIMEOUT;
814 goto _END;
815 }
816
817 if (HimciCmdDatePrepare(cntlr, cmd, host) != HDF_SUCCESS) {
818 goto _END;
819 }
820
821 ret = HimciExecCmd(host);
822 if (ret != HDF_SUCCESS) {
823 cmd->returnError = ret;
824 HimciDmaStop(host);
825 HDF_LOGE("cmd%u exec fail, err = %d!", cmd->cmdCode, ret);
826 goto _END;
827 }
828 HimciWaitCmdComplete(host);
829
830 _END:
831 HimciClearDmaSg(host, cmd->data);
832 host->cmd = NULL;
833 (void)OsalMutexUnlock(&host->mutex);
834 return ret;
835 }
836
HimciControlClock(struct HimciHost * host,bool enableClk)837 static void HimciControlClock(struct HimciHost *host, bool enableClk)
838 {
839 uint32_t value;
840 union HimciCmdRegArg cmdArg;
841
842 value = HIMCI_READL((uintptr_t)host->base + MMC_CLKENA);
843 if (enableClk == true) {
844 value |= CCLK_ENABLE;
845 /* Do not set/clear CCLK_LOW_POWER here,or the cmd18 will timeout. */
846 } else {
847 value &= (~CCLK_ENABLE);
848 }
849 if (host->mmc->devType == MMC_DEV_SDIO) {
850 value &= (~CCLK_LOW_POWER);
851 }
852 HIMCI_WRITEL(value, (uintptr_t)host->base + MMC_CLKENA);
853
854 cmdArg.arg = HIMCI_READL((uintptr_t)host->base + MMC_CMD);
855 cmdArg.bits.startCmd = 1;
856 cmdArg.bits.cardNumber = 0;
857 cmdArg.bits.cmdIndex = 0;
858 cmdArg.bits.dataTransferExpected = 0;
859 cmdArg.bits.useHoldReg = 1;
860 cmdArg.bits.updateClkRegOnly = 1;
861 HIMCI_WRITEL(cmdArg.arg, (uintptr_t)host->base + MMC_CMD);
862
863 if (HimciWaitCmd(host) != HDF_SUCCESS) {
864 HDF_LOGE("dis/enable clk is err!");
865 }
866 }
867
HimciSetCClk(struct HimciHost * host,uint32_t clock)868 static void HimciSetCClk(struct HimciHost *host, uint32_t clock)
869 {
870 uint32_t clk = 0;
871 union HimciCmdRegArg cmdArg;
872 struct MmcCntlr *mmc = host->mmc;
873 struct MmcDevice *dev = mmc->curDev;
874
875 (void)OsalMutexLock(&host->mutex);
876 if (host->id < MMC_CNTLR_NR_MAX) {
877 clk = HimciClkDiv(host, clock);
878 }
879 (void)OsalMutexUnlock(&host->mutex);
880 dev->workPara.clock = clk;
881
882 cmdArg.arg = HIMCI_READL((uintptr_t)host->base + MMC_CMD);
883 cmdArg.bits.startCmd = 1;
884 cmdArg.bits.cardNumber = 0;
885 cmdArg.bits.updateClkRegOnly = 1;
886 cmdArg.bits.cmdIndex = 0;
887 cmdArg.bits.dataTransferExpected = 0;
888 HIMCI_WRITEL(cmdArg.arg, (uintptr_t)host->base + MMC_CMD);
889
890 if (HimciWaitCmd(host) != HDF_SUCCESS) {
891 HDF_LOGE("host%u: set card clk divider is failed!", host->id);
892 }
893 }
894
HimciSetClock(struct MmcCntlr * cntlr,uint32_t clock)895 static int32_t HimciSetClock(struct MmcCntlr *cntlr, uint32_t clock)
896 {
897 struct HimciHost *host = NULL;
898 uint32_t curClock = clock;
899
900 if ((cntlr == NULL) || (cntlr->priv == NULL)) {
901 return HDF_ERR_INVALID_OBJECT;
902 }
903 /* can not greater than max of host. */
904 if (curClock > cntlr->freqMax) {
905 curClock = cntlr->freqMax;
906 }
907
908 host = (struct HimciHost *)cntlr->priv;
909 HimciControlClock(host, false);
910 if (curClock > 0) {
911 HimciSetCClk(host, curClock);
912 HimciControlClock(host, true);
913 }
914 return HDF_SUCCESS;
915 }
916
HimciControlPower(struct HimciHost * host,enum HimciPowerStatus status,bool forceEnable)917 static void HimciControlPower(struct HimciHost *host, enum HimciPowerStatus status, bool forceEnable)
918 {
919 uint32_t value;
920
921 if (host->powerStatus != status || forceEnable == true) {
922 value = HIMCI_READL((uintptr_t)host->base + MMC_PWREN);
923 if (status == HOST_POWER_OFF) {
924 value &= (~POWER_ENABLE);
925 } else {
926 value |= POWER_ENABLE;
927 }
928 HIMCI_WRITEL(value, (uintptr_t)host->base + MMC_PWREN);
929 OsalMDelay(50);
930 host->powerStatus = status;
931 }
932 }
933
HimciSetPowerMode(struct MmcCntlr * cntlr,enum MmcPowerMode mode)934 static int32_t HimciSetPowerMode(struct MmcCntlr *cntlr, enum MmcPowerMode mode)
935 {
936 struct HimciHost *host = NULL;
937 uint32_t value;
938 if ((cntlr == NULL) || (cntlr->priv == NULL)) {
939 return HDF_ERR_INVALID_OBJECT;
940 }
941
942 host = (struct HimciHost *)cntlr->priv;
943 if (mode == MMC_POWER_MODE_POWER_OFF) {
944 value = HIMCI_READL((uintptr_t)host->base + MMC_UHS_REG);
945 value &= (~HI_SDXC_CTRL_VDD_180);
946 HIMCI_WRITEL(value, (uintptr_t)host->base + MMC_UHS_REG);
947 HimciControlPower(host, HOST_POWER_OFF, false);
948 } else {
949 HimciControlPower(host, HOST_POWER_ON, true);
950 }
951 return HDF_SUCCESS;
952 }
953
HimciSetBusWidth(struct MmcCntlr * cntlr,enum MmcBusWidth width)954 static int32_t HimciSetBusWidth(struct MmcCntlr *cntlr, enum MmcBusWidth width)
955 {
956 struct HimciHost *host = NULL;
957 uint32_t value;
958
959 if ((cntlr == NULL) || (cntlr->priv == NULL)) {
960 return HDF_ERR_INVALID_OBJECT;
961 }
962
963 host = (struct HimciHost *)cntlr->priv;
964 value = HIMCI_READL((uintptr_t)host->base + MMC_CTYPE);
965 value &= (~(CARD_WIDTH_0 | CARD_WIDTH_1));
966
967 if (width == BUS_WIDTH8) {
968 value |= CARD_WIDTH_0;
969 HIMCI_WRITEL(value, (uintptr_t)host->base + MMC_CTYPE);
970 } else if (width == BUS_WIDTH4) {
971 value |= CARD_WIDTH_1;
972 HIMCI_WRITEL(value, (uintptr_t)host->base + MMC_CTYPE);
973 } else {
974 HIMCI_WRITEL(value, (uintptr_t)host->base + MMC_CTYPE);
975 }
976 return HDF_SUCCESS;
977 }
978
HimciCfgPhase(struct HimciHost * host,enum MmcBusTiming timing)979 static void HimciCfgPhase(struct HimciHost *host, enum MmcBusTiming timing)
980 {
981 uint32_t value;
982 uint32_t phase;
983 struct MmcDevice *dev = host->mmc->curDev;
984
985 if (dev->type == MMC_DEV_EMMC) {
986 if (timing == BUS_TIMING_MMC_HS200) {
987 phase = DRV_PHASE_135 | SMP_PHASE_0;
988 } else if (timing == BUS_TIMING_MMC_HS) {
989 phase = DRV_PHASE_180 | SMP_PHASE_45;
990 } else {
991 phase = DRV_PHASE_180 | SMP_PHASE_0;
992 }
993 } else {
994 if (timing == BUS_TIMING_UHS_SDR104) {
995 phase = DRV_PHASE_135 | SMP_PHASE_0;
996 } else if (timing == BUS_TIMING_UHS_SDR50) {
997 phase = DRV_PHASE_90 | SMP_PHASE_0;
998 } else if (timing == BUS_TIMING_UHS_SDR25) {
999 phase = DRV_PHASE_180 | SMP_PHASE_45;
1000 } else if (timing == BUS_TIMING_SD_HS) {
1001 phase = DRV_PHASE_135 | SMP_PHASE_45;
1002 } else {
1003 phase = DRV_PHASE_180 | SMP_PHASE_0;
1004 }
1005 }
1006 value = HIMCI_READL((uintptr_t)host->base + MMC_UHS_REG_EXT);
1007 value &= ~CLK_SMPL_PHS_MASK;
1008 value &= ~CLK_DRV_PHS_MASK;
1009 value |= phase;
1010 HIMCI_WRITEL(value, (uintptr_t)host->base + MMC_UHS_REG_EXT);
1011 }
1012
HimciSetBusTiming(struct MmcCntlr * cntlr,enum MmcBusTiming timing)1013 static int32_t HimciSetBusTiming(struct MmcCntlr *cntlr, enum MmcBusTiming timing)
1014 {
1015 struct HimciHost *host = NULL;
1016 uint32_t value;
1017
1018 if ((cntlr == NULL) || (cntlr->priv == NULL)) {
1019 return HDF_ERR_INVALID_OBJECT;
1020 }
1021
1022 host = (struct HimciHost *)cntlr->priv;
1023 value = HIMCI_READL((uintptr_t)host->base + MMC_UHS_REG);
1024 /* speed mode check ,if it is DDR50 set DDR mode */
1025 if (timing == BUS_TIMING_UHS_DDR50) {
1026 if ((value & HI_SDXC_CTRL_DDR_REG) == 0) {
1027 value |= HI_SDXC_CTRL_DDR_REG;
1028 }
1029 } else {
1030 if ((value & HI_SDXC_CTRL_DDR_REG) > 0) {
1031 value &= (~HI_SDXC_CTRL_DDR_REG);
1032 }
1033 }
1034 HIMCI_WRITEL(value, (uintptr_t)host->base + MMC_UHS_REG);
1035 HimciCfgPhase(host, timing);
1036 return HDF_SUCCESS;
1037 }
1038
HimciSetSdioIrq(struct MmcCntlr * cntlr,bool enable)1039 static int32_t HimciSetSdioIrq(struct MmcCntlr *cntlr, bool enable)
1040 {
1041 struct HimciHost *host = NULL;
1042 uint32_t value;
1043 unsigned long flags = 0;
1044
1045 if ((cntlr == NULL) || (cntlr->priv == NULL)) {
1046 return HDF_ERR_INVALID_OBJECT;
1047 }
1048
1049 host = (struct HimciHost *)cntlr->priv;
1050 HIMCI_IRQ_LOCK(&flags);
1051 value = HIMCI_READL((uintptr_t)host->base + MMC_INTMASK);
1052 if (enable == true) {
1053 value |= SDIO_INT_MASK;
1054 } else {
1055 value &= (~SDIO_INT_MASK);
1056 }
1057 HIMCI_WRITEL(value, (uintptr_t)host->base + MMC_INTMASK);
1058 HIMCI_IRQ_UNLOCK(flags);
1059 return HDF_SUCCESS;
1060 }
1061
HimciHardwareReset(struct MmcCntlr * cntlr)1062 static int32_t HimciHardwareReset(struct MmcCntlr *cntlr)
1063 {
1064 uint32_t val;
1065 struct HimciHost *host = NULL;
1066
1067 if ((cntlr == NULL) || (cntlr->priv == NULL)) {
1068 return HDF_ERR_INVALID_OBJECT;
1069 }
1070
1071 host = (struct HimciHost *)cntlr->priv;
1072 val = HIMCI_READL((uintptr_t)host->base + MMC_CARD_RSTN);
1073 val &= (~CARD_RESET);
1074 HIMCI_WRITEL(val, (uintptr_t)host->base + MMC_CARD_RSTN);
1075
1076 /* For eMMC, minimum is 1us but give it 10us for good measure */
1077 OsalUDelay(10);
1078 val = HIMCI_READL((uintptr_t)host->base + MMC_CARD_RSTN);
1079 val |= CARD_RESET;
1080 HIMCI_WRITEL(val, (uintptr_t)host->base + MMC_CARD_RSTN);
1081 OsalUDelay(300);
1082 return HDF_SUCCESS;
1083 }
1084
HimciSetEnhanceStrobe(struct MmcCntlr * cntlr,bool enable)1085 static int32_t HimciSetEnhanceStrobe(struct MmcCntlr *cntlr, bool enable)
1086 {
1087 (void)cntlr;
1088 (void)enable;
1089 return HDF_SUCCESS;
1090 }
1091
HimciVoltageSwitchTo3v3(struct MmcCntlr * cntlr,struct HimciHost * host)1092 static int32_t HimciVoltageSwitchTo3v3(struct MmcCntlr *cntlr, struct HimciHost *host)
1093 {
1094 uint32_t ctrl;
1095
1096 HIMCI_CLEARL(host, MMC_UHS_REG, HI_SDXC_CTRL_VDD_180);
1097 OsalMSleep(10);
1098 ctrl = HIMCI_READL((uintptr_t)host->base + MMC_UHS_REG);
1099 if ((ctrl & HI_SDXC_CTRL_VDD_180) > 0) {
1100 HDF_LOGE("host%u: Switching to 3.3V failed\n", host->id);
1101 return HDF_ERR_IO;
1102 }
1103 HimciSetDrvCap(cntlr);
1104 return HDF_SUCCESS;
1105 }
1106
HimciVoltageSwitchTo1v8(struct MmcCntlr * cntlr,struct HimciHost * host)1107 static int32_t HimciVoltageSwitchTo1v8(struct MmcCntlr *cntlr, struct HimciHost *host)
1108 {
1109 uint32_t ctrl;
1110
1111 ctrl = HIMCI_READL((uintptr_t)host->base + MMC_UHS_REG);
1112 if ((ctrl & HI_SDXC_CTRL_VDD_180) > 0) {
1113 return HDF_SUCCESS;
1114 }
1115
1116 HimciControlClock(host, false);
1117 HIMCI_SETL(host, MMC_UHS_REG, HI_SDXC_CTRL_VDD_180);
1118 OsalMSleep(10);
1119 ctrl = HIMCI_READL((uintptr_t)host->base + MMC_UHS_REG);
1120 if ((ctrl & HI_SDXC_CTRL_VDD_180) > 0) {
1121 HimciControlClock(host, true);
1122 OsalMSleep(10);
1123 if (host->mmc->caps2.bits.hs200Sdr1v8 || host->mmc->caps2.bits.hs200Sdr1v2) {
1124 /* emmc needn't to check the int status. */
1125 return HDF_SUCCESS;
1126 }
1127 /* If CMD11 return CMD down, then the card was successfully switched to 1.8V signaling. */
1128 ctrl = HIMCI_EVENT_WAIT(&host->himciEvent, HIMCI_PEND_DTO_M, HIMCI_VOLT_SWITCH_TIMEOUT);
1129 if ((ctrl & HIMCI_PEND_DTO_M) > 0) {
1130 /* config Pin drive capability */
1131 HimciSetDrvCap(cntlr);
1132 return HDF_SUCCESS;
1133 }
1134 }
1135
1136 ctrl &= (~HI_SDXC_CTRL_VDD_180);
1137 HIMCI_WRITEL(ctrl, (uintptr_t)host->base + MMC_UHS_REG);
1138 OsalMSleep(10);
1139 HimciControlPower(host, HOST_POWER_OFF, false);
1140 OsalMSleep(10);
1141 HimciControlPower(host, HOST_POWER_ON, false);
1142 HimciControlClock(host, false);
1143 OsalMSleep(1);
1144 HimciControlClock(host, true);
1145 ctrl = HIMCI_EVENT_WAIT(&host->himciEvent, HIMCI_PEND_DTO_M, 10);
1146 if ((ctrl & HIMCI_PEND_DTO_M) > 0) {
1147 /* config Pin drive capability */
1148 HimciSetDrvCap(cntlr);
1149 return HDF_SUCCESS;
1150 }
1151
1152 HDF_LOGD("Switching to 1.8V failed, retrying with S18R set to 0.");
1153 return HDF_FAILURE;
1154 }
1155
HimciSwitchVoltage(struct MmcCntlr * cntlr,enum MmcVolt volt)1156 static int32_t HimciSwitchVoltage(struct MmcCntlr *cntlr, enum MmcVolt volt)
1157 {
1158 struct HimciHost *host = NULL;
1159
1160 if ((cntlr == NULL) || (cntlr->priv == NULL)) {
1161 return HDF_ERR_INVALID_OBJECT;
1162 }
1163
1164 host = (struct HimciHost *)cntlr->priv;
1165 if (volt == VOLT_3V3) {
1166 return HimciVoltageSwitchTo3v3(cntlr, host);
1167 } else if (volt == VOLT_1V8) {
1168 return HimciVoltageSwitchTo1v8(cntlr, host);
1169 }
1170 return HDF_SUCCESS;
1171 }
1172
HimciDevReadOnly(struct MmcCntlr * cntlr)1173 static bool HimciDevReadOnly(struct MmcCntlr *cntlr)
1174 {
1175 struct HimciHost *host = NULL;
1176 uint32_t val;
1177
1178 if ((cntlr == NULL) || (cntlr->priv == NULL)) {
1179 return false;
1180 }
1181
1182 host = (struct HimciHost *)cntlr->priv;
1183 val = HIMCI_READL((uintptr_t)host->base + MMC_WRTPRT);
1184 if ((val & CARD_READONLY) > 0) {
1185 return true;
1186 }
1187 return false;
1188 }
1189
HimciDevBusy(struct MmcCntlr * cntlr)1190 static bool HimciDevBusy(struct MmcCntlr *cntlr)
1191 {
1192 (void)cntlr;
1193 return false;
1194 }
1195
HimciEdgeTuningEnable(struct HimciHost * host)1196 static void HimciEdgeTuningEnable(struct HimciHost *host)
1197 {
1198 uint32_t val;
1199 uint32_t regs[] = { PERI_CRG83, PERI_CRG89, PERI_CRG86 };
1200
1201 if (host->id >= MMC_CNTLR_NR_MAX) {
1202 HDF_LOGE("host%u id error", host->id);
1203 return;
1204 }
1205
1206 HIMCI_WRITEL((HIMCI_SAP_DLL_SOFT_RESET | HIMCI_SAP_DLL_DEVICE_DELAY_ENABLE), regs[host->id]);
1207
1208 val = HIMCI_READL((uintptr_t)host->base + MMC_TUNING_CTRL);
1209 val |= HW_TUNING_EN;
1210 HIMCI_WRITEL(val, (uintptr_t)host->base + MMC_TUNING_CTRL);
1211 }
1212
HimciSetSapPhase(struct HimciHost * host,uint32_t phase)1213 static void HimciSetSapPhase(struct HimciHost *host, uint32_t phase)
1214 {
1215 uint32_t val;
1216
1217 val = HIMCI_READL((uintptr_t)host->base + MMC_UHS_REG_EXT);
1218 val &= ~CLK_SMPL_PHS_MASK;
1219 val |= (phase << CLK_SMPL_PHS_OFFSET);
1220 HIMCI_WRITEL(val, (uintptr_t)host->base + MMC_UHS_REG_EXT);
1221 }
1222
HimciEdgeTuningDisable(struct HimciHost * host)1223 static void HimciEdgeTuningDisable(struct HimciHost *host)
1224 {
1225 uint32_t val;
1226 uint32_t regs[] = { PERI_CRG83, PERI_CRG89, PERI_CRG86 };
1227
1228 if (host->id >= MMC_CNTLR_NR_MAX) {
1229 HDF_LOGE("host%u id error", host->id);
1230 return;
1231 }
1232
1233 val = HIMCI_READL(regs[host->id]);
1234 val |= HIMCI_SAP_DLL_MODE_DLLSSEL;
1235 HIMCI_WRITEL(val, regs[host->id]);
1236
1237 val = HIMCI_READL((uintptr_t)host->base + MMC_TUNING_CTRL);
1238 val &= ~HW_TUNING_EN;
1239 HIMCI_WRITEL(val, (uintptr_t)host->base + MMC_TUNING_CTRL);
1240 }
1241
HimciSendTuning(struct MmcCntlr * cntlr,uint32_t opcode)1242 static int32_t HimciSendTuning(struct MmcCntlr *cntlr, uint32_t opcode)
1243 {
1244 int32_t err;
1245 uint32_t result;
1246 struct HimciHost *host = (struct HimciHost *)cntlr->priv;
1247
1248 (void)OsalMutexLock(&host->mutex);
1249 HimciControlClock(host, false);
1250 HimciDmaReset(host);
1251 HimciControlClock(host, true);
1252 (void)OsalMutexUnlock(&host->mutex);
1253
1254 err = MmcSendTuning(cntlr, opcode, true);
1255 (void)MmcStopTransmission(cntlr, true, &result);
1256 (void)MmcSendStatus(cntlr, &result);
1257 return err;
1258 }
1259
HimciSysReset(struct HimciHost * host)1260 static void HimciSysReset(struct HimciHost *host)
1261 {
1262 uint32_t value;
1263
1264 value = HIMCI_READL((uintptr_t)host->base + MMC_BMOD);
1265 value |= BMOD_SWR;
1266 HIMCI_WRITEL(value, (uintptr_t)host->base + MMC_BMOD);
1267 OsalUDelay(10);
1268
1269 value = HIMCI_READL((uintptr_t)host->base + MMC_BMOD);
1270 value |= (BURST_INCR | BURST_16);
1271 HIMCI_WRITEL(value, (uintptr_t)host->base + MMC_BMOD);
1272
1273 value = HIMCI_READL((uintptr_t)host->base + MMC_CTRL);
1274 value |= (CTRL_RESET | FIFO_RESET | DMA_RESET);
1275 HIMCI_WRITEL(value, (uintptr_t)host->base + MMC_CTRL);
1276 }
1277
HimciTuningFeedback(struct MmcCntlr * cntlr)1278 static void HimciTuningFeedback(struct MmcCntlr *cntlr)
1279 {
1280 struct HimciHost *host = (struct HimciHost *)cntlr->priv;
1281
1282 (void)OsalMutexLock(&host->mutex);
1283 HimciControlClock(host, false);
1284 OsalMDelay(1);
1285 HimciSysReset(host);
1286 OsalMDelay(1);
1287 HIMCI_WRITEL(ALL_INT_CLR, (uintptr_t)host->base + MMC_RINTSTS);
1288 HimciControlClock(host, true);
1289 OsalMDelay(1);
1290 (void)OsalMutexUnlock(&host->mutex);
1291 }
1292
HimciGetSapDllTaps(struct HimciHost * host)1293 static uint32_t HimciGetSapDllTaps(struct HimciHost *host)
1294 {
1295 uint32_t val;
1296 uint32_t regs[] = { PERI_CRG84, PERI_CRG90, PERI_CRG87 };
1297
1298 if (host->id >= MMC_CNTLR_NR_MAX) {
1299 HDF_LOGE("host%u id error", host->id);
1300 return 0;
1301 }
1302
1303 val = HIMCI_READL(regs[host->id]);
1304 return (val & 0xff);
1305 }
1306
HimciSetDllElement(struct HimciHost * host,uint32_t element)1307 static void HimciSetDllElement(struct HimciHost *host, uint32_t element)
1308 {
1309 uint32_t val;
1310 uint32_t regs[] = { PERI_CRG83, PERI_CRG89, PERI_CRG86 };
1311
1312 if (host->id >= MMC_CNTLR_NR_MAX) {
1313 HDF_LOGE("host%u id error", host->id);
1314 return;
1315 }
1316
1317 val = HIMCI_READL(regs[host->id]);
1318 val &= ~(0xFF << HIMCI_SAP_DLL_ELEMENT_SHIFT);
1319 val |= (element << HIMCI_SAP_DLL_ELEMENT_SHIFT);
1320 HIMCI_WRITEL(val, regs[host->id]);
1321 }
1322
HimciEdgedllModeATuning(struct HimciHost * host,struct HimciTuneParam * param,uint32_t phaseDllElements)1323 static void HimciEdgedllModeATuning(struct HimciHost *host, struct HimciTuneParam *param,
1324 uint32_t phaseDllElements)
1325 {
1326 uint32_t index, ele, phaseOffset;
1327 int32_t prevErr = HDF_SUCCESS;
1328 int32_t err;
1329
1330 if (host == NULL || param == NULL) {
1331 return;
1332 }
1333
1334 phaseOffset = param->edgeP2f * phaseDllElements;
1335 for (index = param->edgeP2f; index < param->edgeF2p; index++) {
1336 HimciSetSapPhase(host, index);
1337 for (ele = HIMCI_PHASE_DLL_START_ELEMENT; ele <= phaseDllElements; ele++) {
1338 HimciSetDllElement(host, ele);
1339 err = HimciSendTuning(host->mmc, param->cmdCode);
1340 if (prevErr == HDF_SUCCESS && err != HDF_SUCCESS && (param->endp == param->endpInit)) {
1341 param->endp = phaseOffset + ele;
1342 }
1343
1344 if (err != HDF_SUCCESS) {
1345 param->startp = phaseOffset + ele;
1346 }
1347 prevErr = err;
1348 err = HDF_SUCCESS;
1349 }
1350 phaseOffset += phaseDllElements;
1351 }
1352 }
1353
HimciEdgedllModeBTuning(struct HimciHost * host,struct HimciTuneParam * param,uint32_t phaseDllElements)1354 static void HimciEdgedllModeBTuning(struct HimciHost *host, struct HimciTuneParam *param,
1355 uint32_t phaseDllElements)
1356 {
1357 uint32_t index, ele, phaseOffset;
1358 int32_t prevErr = HDF_SUCCESS;
1359 int32_t err;
1360
1361 if (host == NULL || param == NULL) {
1362 return;
1363 }
1364
1365 phaseOffset = param->edgeP2f * phaseDllElements;
1366 for (index = param->edgeP2f; index < HIMCI_PHASE_SCALE; index++) {
1367 HimciSetSapPhase(host, index);
1368 for (ele = HIMCI_PHASE_DLL_START_ELEMENT; ele <= phaseDllElements; ele++) {
1369 HimciSetDllElement(host, ele);
1370 err = HimciSendTuning(host->mmc, param->cmdCode);
1371 if (prevErr == HDF_SUCCESS && err != HDF_SUCCESS && (param->endp == param->endpInit)) {
1372 param->endp = phaseOffset + ele;
1373 }
1374 if (err != HDF_SUCCESS) {
1375 param->startp = phaseOffset + ele;
1376 }
1377 prevErr = err;
1378 err = HDF_SUCCESS;
1379 }
1380 phaseOffset += phaseDllElements;
1381 }
1382
1383 phaseOffset = 0;
1384 for (index = 0; index < param->edgeF2p; index++) {
1385 HimciSetSapPhase(host, index);
1386 for (ele = HIMCI_PHASE_DLL_START_ELEMENT; ele <= phaseDllElements; ele++) {
1387 HimciSetDllElement(host, ele);
1388 err = HimciSendTuning(host->mmc, param->cmdCode);
1389 if (prevErr == HDF_SUCCESS && err != HDF_SUCCESS && (param->endp == param->endpInit)) {
1390 param->endp = phaseOffset + ele;
1391 }
1392 if (err != HDF_SUCCESS) {
1393 param->startp = phaseOffset + ele;
1394 }
1395 prevErr = err;
1396 err = HDF_SUCCESS;
1397 }
1398 phaseOffset += phaseDllElements;
1399 }
1400 }
1401
HimciEdgedllModeTuning(struct HimciHost * host,uint32_t cmdCode,uint32_t edgeP2f,uint32_t edgeF2p)1402 static int32_t HimciEdgedllModeTuning(struct HimciHost *host,
1403 uint32_t cmdCode, uint32_t edgeP2f, uint32_t edgeF2p)
1404 {
1405 uint32_t index, ele, phaseOffset, totalPhases, phaseDllElements;
1406 struct HimciTuneParam param = {0};
1407
1408 phaseDllElements = HimciGetSapDllTaps(host) / HIMCI_PHASE_SCALE;
1409 totalPhases = phaseDllElements * HIMCI_PHASE_SCALE;
1410 /*
1411 * EdgeMode A:
1412 * |<---- totalphases(ele) ---->|
1413 * _____________
1414 * ______|||||||||||||||_______
1415 * edge_p2f edge_f2p
1416 * (endp) (startp)
1417 *
1418 * EdgeMode B:
1419 * |<---- totalphases(ele) ---->|
1420 * ________ _________
1421 * ||||||||||_________|||||||||||
1422 * edge_f2p edge_p2f
1423 * (startp) (endp)
1424 *
1425 * BestPhase:
1426 * if(endp < startp)
1427 * endp = endp + totalphases;
1428 * Best = ((startp + endp) / 2) % totalphases
1429 */
1430 param.cmdCode = cmdCode;
1431 param.edgeF2p = edgeF2p;
1432 param.edgeP2f = edgeP2f;
1433 param.endpInit = edgeP2f * phaseDllElements;
1434 param.startp = edgeF2p * phaseDllElements;
1435 param.endp = param.endpInit;
1436 if (edgeF2p >= edgeP2f) {
1437 HimciEdgedllModeATuning(host, ¶m, phaseDllElements);
1438 } else {
1439 HimciEdgedllModeBTuning(host, ¶m, phaseDllElements);
1440 }
1441
1442 if (param.endp <= param.startp) {
1443 param.endp += totalPhases;
1444 }
1445 if (totalPhases == 0) {
1446 HDF_LOGE("host%u:total phases is zero.", host->id);
1447 return HDF_FAILURE;
1448 }
1449 phaseOffset = ((param.startp + param.endp) / 2) % totalPhases;
1450 index = (phaseOffset / phaseDllElements);
1451 ele = (phaseOffset % phaseDllElements);
1452 ele = ((ele > HIMCI_PHASE_DLL_START_ELEMENT) ? ele : HIMCI_PHASE_DLL_START_ELEMENT);
1453 HimciSetSapPhase(host, index);
1454 HimciSetDllElement(host, ele);
1455 HIMCI_WRITEL(ALL_INT_CLR, (uintptr_t)host->base + MMC_RINTSTS);
1456 return HDF_SUCCESS;
1457 }
1458
HimciTune(struct MmcCntlr * cntlr,uint32_t cmdCode)1459 static int32_t HimciTune(struct MmcCntlr *cntlr, uint32_t cmdCode)
1460 {
1461 struct HimciHost *host = NULL;
1462 uint32_t index, val;
1463 bool found = false;
1464 bool prevFound = false;
1465 uint32_t edgeP2f = 0;
1466 uint32_t phaseNum = HIMCI_PHASE_SCALE;
1467 uint32_t edgeF2p = HIMCI_PHASE_SCALE;
1468 int32_t err;
1469
1470 if ((cntlr == NULL) || (cntlr->priv == NULL)) {
1471 return HDF_ERR_INVALID_OBJECT;
1472 }
1473
1474 host = (struct HimciHost *)cntlr->priv;
1475 host->isTuning = true;
1476 HimciEdgeTuningEnable(host);
1477 for (index = 0; index < HIMCI_PHASE_SCALE; index++) {
1478 found = true;
1479 HimciSetSapPhase(host, index);
1480 err = HimciSendTuning(cntlr, cmdCode);
1481 if (err == HDF_SUCCESS) {
1482 val = HIMCI_READL((uintptr_t)host->base + MMC_TUNING_CTRL);
1483 found = ((val & FOUND_EDGE) == FOUND_EDGE);
1484 }
1485
1486 if (prevFound == true && found == false) {
1487 edgeF2p = index;
1488 } else if (prevFound == false && found == true) {
1489 edgeP2f = index;
1490 }
1491
1492 if ((edgeP2f != 0) && (edgeF2p != phaseNum)) {
1493 break;
1494 }
1495 prevFound = found;
1496 }
1497
1498 if ((edgeP2f == 0) && (edgeF2p == phaseNum)) {
1499 host->isTuning = false;
1500 return HDF_FAILURE;
1501 }
1502
1503 index = (edgeF2p + phaseNum + edgeP2f) / 2 % phaseNum;
1504 if (edgeF2p < edgeP2f) {
1505 index = (edgeF2p + edgeP2f) / 2 % phaseNum;
1506 }
1507 HimciSetSapPhase(host, index);
1508 err = HimciSendTuning(cntlr, cmdCode);
1509 HimciEdgeTuningDisable(host);
1510
1511 err = HimciEdgedllModeTuning(host, cmdCode, edgeP2f, edgeF2p);
1512 HimciTuningFeedback(cntlr);
1513 if (err == HDF_SUCCESS) {
1514 (void)HimciSendTuning(cntlr, cmdCode);
1515 }
1516
1517 host->isTuning = false;
1518 return HDF_SUCCESS;
1519 }
1520
HimciClockCfg(uint32_t devId)1521 static void HimciClockCfg(uint32_t devId)
1522 {
1523 uint32_t val;
1524 uint32_t regs[] = { PERI_CRG82, PERI_CRG88, PERI_CRG85 };
1525
1526 if (devId < MMC_CNTLR_NR_MAX) {
1527 val = HIMCI_READL((uintptr_t)regs[devId]);
1528 val |= HIMCI_CLK_SEL_100M;
1529 val |= HIMCI_CKEN;
1530 HIMCI_WRITEL(val, (uintptr_t)regs[devId]);
1531 }
1532 }
1533
HimciSoftReset(uint32_t devId)1534 static void HimciSoftReset(uint32_t devId)
1535 {
1536 uint32_t regs[] = { PERI_CRG82, PERI_CRG88, PERI_CRG85 };
1537 uint32_t val;
1538
1539 if (devId < MMC_CNTLR_NR_MAX) {
1540 val = HIMCI_READL((uintptr_t)regs[devId]);
1541 OsalUDelay(1000);
1542 val |= HIMCI_RESET;
1543 HIMCI_WRITEL(val, (uintptr_t)regs[devId]);
1544 val &= ~HIMCI_RESET;
1545 HIMCI_WRITEL(val, (uintptr_t)regs[devId]);
1546 }
1547 }
1548
HimciSysCtrlInit(struct HimciHost * host)1549 static void HimciSysCtrlInit(struct HimciHost *host)
1550 {
1551 HIMCI_TASK_LOCK();
1552 HimciClockCfg(host->id);
1553 HimciSoftReset(host->id);
1554 HIMCI_TASK_UNLOCK();
1555 }
1556
HimciHostRegistersInit(struct HimciHost * host)1557 static void HimciHostRegistersInit(struct HimciHost *host)
1558 {
1559 uint32_t value;
1560
1561 HimciSysReset(host);
1562 HimciControlPower(host, HOST_POWER_OFF, true);
1563 /* host power on */
1564 HimciControlPower(host, HOST_POWER_ON, true);
1565
1566 /*
1567 * Walkaround: controller config gpio
1568 * the value of this register should be 0x80a400,
1569 * but the reset value is 0xa400.
1570 */
1571 value = HIMCI_READL((uintptr_t)host->base + MMC_GPIO);
1572 value |= DTO_FIX_ENABLE;
1573 HIMCI_WRITEL(value, (uintptr_t)host->base + MMC_GPIO);
1574
1575 value = ((DRV_PHASE_SHIFT << CLK_DRV_PHS_OFFSET)
1576 | (SMPL_PHASE_SHIFT << CLK_SMPL_PHS_OFFSET));
1577 HIMCI_WRITEL(value, (uintptr_t)host->base + MMC_UHS_REG_EXT);
1578
1579 HIMCI_WRITEL((READ_THRESHOLD_SIZE | BUSY_CLEAR_INT_ENABLE), (uintptr_t)host->base + MMC_CARDTHRCTL);
1580
1581 /* clear MMC host intr */
1582 HIMCI_WRITEL(ALL_INT_CLR, (uintptr_t)host->base + MMC_RINTSTS);
1583
1584 /*
1585 * data transfer over(DTO) interrupt comes after ACD
1586 * we'd use DTO with or without auto_cmd is enabled.
1587 */
1588 value = ALL_INT_MASK & (~(ACD_INT_STATUS | RXDR_INT_STATUS | TXDR_INT_STATUS | SDIO_INT_MASK));
1589 HIMCI_WRITEL(value, (uintptr_t)host->base + MMC_INTMASK);
1590 HIMCI_WRITEL(DEBNCE_MS, (uintptr_t)host->base + MMC_DEBNCE);
1591
1592 /* enable inner DMA mode and close intr of MMC host controler */
1593 value = HIMCI_READL((uintptr_t)host->base + MMC_CTRL);
1594 value |= USE_INTERNAL_DMA | INTR_EN;
1595 HIMCI_WRITEL(value, (uintptr_t)host->base + MMC_CTRL);
1596
1597 /* set timeout param */
1598 HIMCI_WRITEL(DATA_TIMEOUT | RESPONSE_TIMEOUT, (uintptr_t)host->base + MMC_TMOUT);
1599
1600 /* set FIFO param */
1601 value = BURST_SIZE | RX_WMARK | TX_WMARK;
1602 HIMCI_WRITEL(value, (uintptr_t)host->base + MMC_FIFOTH);
1603 }
1604
HimciRescanSdioDev(struct MmcCntlr * cntlr)1605 static int32_t HimciRescanSdioDev(struct MmcCntlr *cntlr)
1606 {
1607 struct HimciHost *host = NULL;
1608
1609 if ((cntlr == NULL) || (cntlr->priv == NULL)) {
1610 return HDF_ERR_INVALID_OBJECT;
1611 }
1612
1613 host = (struct HimciHost *)cntlr->priv;
1614 if (host->waitForEvent == true) {
1615 (void)HIMCI_EVENT_SIGNAL(&host->himciEvent, HIMCI_PEND_ACCIDENT);
1616 }
1617
1618 return MmcCntlrAddSdioRescanMsgToQueue(cntlr);
1619 }
1620
HimciSystemInit(struct MmcCntlr * cntlr)1621 static int32_t HimciSystemInit(struct MmcCntlr *cntlr)
1622 {
1623 struct HimciHost *host = NULL;
1624
1625 if ((cntlr == NULL) || (cntlr->priv == NULL)) {
1626 return HDF_ERR_INVALID_OBJECT;
1627 }
1628
1629 host = (struct HimciHost *)cntlr->priv;
1630 HimciSysCtrlInit(host);
1631 HimciHostRegistersInit(host);
1632 return HDF_SUCCESS;
1633 }
1634
1635 static struct MmcCntlrOps g_himciHostOps = {
1636 .request = HimciDoRequest,
1637 .setClock = HimciSetClock,
1638 .setPowerMode = HimciSetPowerMode,
1639 .setBusWidth = HimciSetBusWidth,
1640 .setBusTiming = HimciSetBusTiming,
1641 .setSdioIrq = HimciSetSdioIrq,
1642 .hardwareReset = HimciHardwareReset,
1643 .systemInit = HimciSystemInit,
1644 .setEnhanceStrobe = HimciSetEnhanceStrobe,
1645 .switchVoltage = HimciSwitchVoltage,
1646 .devReadOnly = HimciDevReadOnly,
1647 .devPlugged = HimciCardPlugged,
1648 .devBusy = HimciDevBusy,
1649 .tune = HimciTune,
1650 .rescanSdioDev = HimciRescanSdioDev,
1651 };
1652
HimciCmdIrq(struct HimciHost * host,uint32_t state)1653 static uint32_t HimciCmdIrq(struct HimciHost *host, uint32_t state)
1654 {
1655 struct MmcCmd *cmd = host->cmd;
1656 struct MmcData *data = NULL;
1657 uint32_t writeEvent = 0;
1658 uint32_t mask;
1659 int32_t error = HDF_SUCCESS;
1660
1661 if ((state & RTO_INT_STATUS) > 0) {
1662 error = HDF_ERR_TIMEOUT;
1663 } else if ((state & (RCRC_INT_STATUS | RE_INT_STATUS)) > 0) {
1664 error = HDF_MMC_ERR_ILLEGAL_SEQ;
1665 }
1666
1667 mask = (CD_INT_STATUS | VOLT_SWITCH_INT_STATUS);
1668 if (cmd != NULL) {
1669 data = cmd->data;
1670 }
1671 if (data == NULL && (state & mask) > 0) {
1672 writeEvent = 1;
1673 }
1674
1675 /*
1676 * If there is a response timeout(RTO) error,
1677 * then the DWC_mobile_storage does not attempt any data transfer and
1678 * the "data Transfer Over" bit is never set.
1679 */
1680 mask = (CD_INT_STATUS | RTO_INT_STATUS);
1681 if ((state & mask) == mask) {
1682 writeEvent = 1;
1683 }
1684 if (cmd != NULL) {
1685 cmd->returnError = error;
1686 }
1687 return writeEvent;
1688 }
1689
HimciDataIrq(struct HimciHost * host,struct MmcData * data,uint32_t state)1690 static uint32_t HimciDataIrq(struct HimciHost *host, struct MmcData *data, uint32_t state)
1691 {
1692 uint32_t writeEvent = 0;
1693
1694 if (host == NULL || data == NULL) {
1695 return writeEvent;
1696 }
1697
1698 if ((data->dataFlags & DATA_READ) == 0) {
1699 if ((state & SBE_INT_STATUS) > 0) {
1700 HimciDmaStop(host);
1701 HimciDataDone(host, state & (~SBE_INT_STATUS));
1702 writeEvent++;
1703 }
1704 } else {
1705 HimciDmaStop(host);
1706 HimciDataDone(host, state);
1707 writeEvent++;
1708 }
1709 return writeEvent;
1710 }
1711
HimciIrqHandler(uint32_t irq,void * data)1712 static uint32_t HimciIrqHandler(uint32_t irq, void *data)
1713 {
1714 struct HimciHost *host = (struct HimciHost *)data;
1715 struct MmcCmd *cmd = NULL;
1716 uint32_t writeEvent = 0;
1717 uint32_t state;
1718 (void)irq;
1719
1720 if (host == NULL) {
1721 HDF_LOGE("HimciIrqHandler: data is null!");
1722 return HDF_SUCCESS;
1723 }
1724 state = HIMCI_READL((uintptr_t)host->base + MMC_RINTSTS);
1725 HIMCI_WRITEL(state, (uintptr_t)host->base + MMC_RINTSTS);
1726 if ((state & SDIO_INT_STATUS) > 0) {
1727 HIMCI_CLEARL(host, MMC_INTMASK, SDIO_INT_MASK);
1728 (void)MmcCntlrNotifySdioIrqThread(host->mmc);
1729 }
1730
1731 if ((state & CARD_DETECT_INT_STATUS) > 0) {
1732 (void)MmcCntlrAddPlugMsgToQueue(host->mmc);
1733 if (host->waitForEvent == true) {
1734 (void)HIMCI_EVENT_SIGNAL(&host->himciEvent, HIMCI_PEND_ACCIDENT);
1735 return HDF_SUCCESS;
1736 }
1737 }
1738
1739 cmd = host->cmd;
1740 if (cmd == NULL) {
1741 return HDF_SUCCESS;
1742 }
1743
1744 if ((state & CMD_INT_MASK) > 0) {
1745 writeEvent += HimciCmdIrq(host, state);
1746 }
1747
1748 if ((state & DATA_INT_MASK) > 0) {
1749 /*
1750 * SBE_INT_STATUS:
1751 * Busy Clear Interrupt when data is written to the card
1752 * In this case, we'd wait for it.
1753 * Error in data start bit when data is read from a card
1754 * In this case, we don't need to wait for it. if it's triggered, something is wrong
1755 */
1756 if (cmd->data != NULL) {
1757 writeEvent += HimciDataIrq(host, cmd->data, state);
1758 } else {
1759 writeEvent += HimciCmdIrq(host, state);
1760 }
1761 }
1762 if (writeEvent != 0) {
1763 (void)HIMCI_EVENT_SIGNAL(&host->himciEvent, HIMCI_PEND_DTO_M);
1764 }
1765 return HDF_SUCCESS;
1766 }
1767
HimciHostInit(struct HimciHost * host,struct MmcCntlr * cntlr)1768 static int32_t HimciHostInit(struct HimciHost *host, struct MmcCntlr *cntlr)
1769 {
1770 int32_t ret;
1771
1772 host->id = (uint32_t)cntlr->index;
1773 host->dmaVaddr = (uint32_t *)LOS_DmaMemAlloc(&host->dmaPaddr, HIMCI_PAGE_SIZE, CACHE_ALIGNED_SIZE, DMA_CACHE);
1774 if (host->dmaVaddr == NULL) {
1775 HDF_LOGE("HimciHostInit: no mem for himci dma!");
1776 return HDF_ERR_MALLOC_FAIL;
1777 }
1778
1779 if (HIMCI_EVENT_INIT(&host->himciEvent) != HDF_SUCCESS) {
1780 HDF_LOGE("HimciHostInit: himciEvent init fail!");
1781 return HDF_FAILURE;
1782 }
1783 if (OsalMutexInit(&host->mutex) != HDF_SUCCESS) {
1784 HDF_LOGE("HimciHostInit: init mutex lock fail!");
1785 return HDF_FAILURE;
1786 }
1787
1788 HimciSysCtrlInit(host);
1789 HimciHostRegistersInit(host);
1790
1791 ret = OsalRegisterIrq(host->irqNum, 0, HimciIrqHandler, "MMC_IRQ", host);
1792 if (ret != HDF_SUCCESS) {
1793 HDF_LOGE("HimciHostInit: request irq for himci is err.");
1794 return HDF_FAILURE;
1795 }
1796 return HDF_SUCCESS;
1797 }
1798
HimciHostParse(struct HimciHost * host,struct HdfDeviceObject * obj)1799 static int32_t HimciHostParse(struct HimciHost *host, struct HdfDeviceObject *obj)
1800 {
1801 const struct DeviceResourceNode *node = NULL;
1802 struct DeviceResourceIface *drsOps = NULL;
1803 int32_t ret;
1804 uint32_t regBase, regSize;
1805
1806 if (obj == NULL || host == NULL) {
1807 HDF_LOGE("%s: input param is NULL.", __func__);
1808 return HDF_FAILURE;
1809 }
1810
1811 node = obj->property;
1812 if (node == NULL) {
1813 HDF_LOGE("%s: drs node is NULL.", __func__);
1814 return HDF_FAILURE;
1815 }
1816 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
1817 if (drsOps == NULL || drsOps->GetUint32 == NULL) {
1818 HDF_LOGE("%s: invalid drs ops fail!", __func__);
1819 return HDF_FAILURE;
1820 }
1821
1822 ret = drsOps->GetUint32(node, "regBasePhy", ®Base, 0);
1823 if (ret != HDF_SUCCESS) {
1824 HDF_LOGE("%s: read regBasePhy fail!", __func__);
1825 return ret;
1826 }
1827
1828 ret = drsOps->GetUint32(node, "regSize", ®Size, 0);
1829 if (ret != HDF_SUCCESS) {
1830 HDF_LOGE("%s: read regSize fail!", __func__);
1831 return ret;
1832 }
1833
1834 host->base = OsalIoRemap(regBase, regSize);
1835 if (host->base == NULL) {
1836 HDF_LOGE("%s: ioremap regBase fail!", __func__);
1837 return HDF_ERR_IO;
1838 }
1839
1840 ret = drsOps->GetUint32(node, "irqNum", &(host->irqNum), 0);
1841 if (ret != HDF_SUCCESS) {
1842 HDF_LOGE("%s: read irqNum fail!", __func__);
1843 }
1844 return ret;
1845 }
1846
HimciDeleteHost(struct HimciHost * host)1847 static void HimciDeleteHost(struct HimciHost *host)
1848 {
1849 struct MmcCntlr *cntlr = NULL;
1850
1851 if (host == NULL) {
1852 return;
1853 }
1854
1855 cntlr = host->mmc;
1856 if (cntlr != NULL) {
1857 if (cntlr->curDev != NULL) {
1858 MmcDeviceRemove(cntlr->curDev);
1859 OsalMemFree(cntlr->curDev);
1860 cntlr->curDev = NULL;
1861 }
1862 MmcCntlrRemove(cntlr);
1863 cntlr->hdfDevObj = NULL;
1864 cntlr->priv = NULL;
1865 cntlr->ops = NULL;
1866 OsalMemFree(cntlr);
1867 host->mmc = NULL;
1868 }
1869
1870 OsalUnregisterIrq(host->irqNum, host);
1871 if (host->dmaVaddr != NULL) {
1872 LOS_DmaMemFree(host->dmaVaddr);
1873 }
1874 if (host->base != NULL) {
1875 OsalIoUnmap(host->base);
1876 }
1877
1878 (void)HIMCI_EVENT_DELETE(&host->himciEvent);
1879 (void)OsalMutexDestroy(&host->mutex);
1880 OsalMemFree(host);
1881 }
1882
HimciMmcBind(struct HdfDeviceObject * obj)1883 static int32_t HimciMmcBind(struct HdfDeviceObject *obj)
1884 {
1885 struct MmcCntlr *cntlr = NULL;
1886 struct HimciHost *host = NULL;
1887 int32_t ret;
1888
1889 if (obj == NULL) {
1890 HDF_LOGE("HimciMmcBind: Fail, device is NULL.");
1891 return HDF_ERR_INVALID_OBJECT;
1892 }
1893 cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr));
1894 if (cntlr == NULL) {
1895 HDF_LOGE("HimciMmcBind: no mem for MmcCntlr.");
1896 return HDF_ERR_MALLOC_FAIL;
1897 }
1898 host = (struct HimciHost *)OsalMemCalloc(sizeof(struct HimciHost));
1899 if (host == NULL) {
1900 HDF_LOGE("HimciMmcBind: no mem for HimciHost.");
1901 OsalMemFree(cntlr);
1902 return HDF_ERR_MALLOC_FAIL;
1903 }
1904
1905 host->mmc = cntlr;
1906 cntlr->priv = (void *)host;
1907 cntlr->ops = &g_himciHostOps;
1908 cntlr->hdfDevObj = obj;
1909 obj->service = &cntlr->service;
1910 /* init cntlr. */
1911 ret = MmcCntlrParse(cntlr, obj);
1912 if (ret != HDF_SUCCESS) {
1913 goto _ERR;
1914 }
1915 /* init host. */
1916 ret = HimciHostParse(host, obj);
1917 if (ret != HDF_SUCCESS) {
1918 goto _ERR;
1919 }
1920 ret = HimciHostInit(host, cntlr);
1921 if (ret != HDF_SUCCESS) {
1922 goto _ERR;
1923 }
1924 ret = MmcCntlrAdd(cntlr, true);
1925 if (ret != HDF_SUCCESS) {
1926 goto _ERR;
1927 }
1928
1929 /* add card detect msg to queue. */
1930 (void)MmcCntlrAddDetectMsgToQueue(cntlr);
1931 HDF_LOGI("%s: mmc bind success.", __func__);
1932 return HDF_SUCCESS;
1933 _ERR:
1934 HimciDeleteHost(host);
1935 HDF_LOGE("HimciMmcBind: fail, err = %d.", ret);
1936 return ret;
1937 }
1938
HimciMmcInit(struct HdfDeviceObject * obj)1939 static int32_t HimciMmcInit(struct HdfDeviceObject *obj)
1940 {
1941 static bool procInit = false;
1942
1943 (void)obj;
1944 if (procInit == false) {
1945 if (ProcMciInit() == HDF_SUCCESS) {
1946 procInit = true;
1947 }
1948 }
1949 HDF_LOGI("%s: mmc init success.", __func__);
1950 return HDF_SUCCESS;
1951 }
1952
HimciMmcRelease(struct HdfDeviceObject * obj)1953 static void HimciMmcRelease(struct HdfDeviceObject *obj)
1954 {
1955 struct MmcCntlr *cntlr = NULL;
1956
1957 HDF_LOGI("%s: enter", __func__);
1958 if (obj == NULL) {
1959 return;
1960 }
1961
1962 cntlr = (struct MmcCntlr *)obj->service;
1963 if (cntlr == NULL) {
1964 return;
1965 }
1966 HimciDeleteHost((struct HimciHost *)cntlr->priv);
1967 }
1968
1969 struct HdfDriverEntry g_mmcDriverEntry = {
1970 .moduleVersion = 1,
1971 .Bind = HimciMmcBind,
1972 .Init = HimciMmcInit,
1973 .Release = HimciMmcRelease,
1974 .moduleName = "hi3516_mmc_driver",
1975 };
1976 HDF_INIT(g_mmcDriverEntry);
1977