1757bff49SJaehoon Chung /* 2757bff49SJaehoon Chung * (C) Copyright 2012 SAMSUNG Electronics 3757bff49SJaehoon Chung * Jaehoon Chung <jh80.chung@samsung.com> 4757bff49SJaehoon Chung * Rajeshawari Shinde <rajeshwari.s@samsung.com> 5757bff49SJaehoon Chung * 61a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 7757bff49SJaehoon Chung */ 8757bff49SJaehoon Chung 92a7a210eSAlexey Brodkin #include <bouncebuf.h> 10757bff49SJaehoon Chung #include <common.h> 11757bff49SJaehoon Chung #include <malloc.h> 12757bff49SJaehoon Chung #include <mmc.h> 13757bff49SJaehoon Chung #include <dwmmc.h> 14757bff49SJaehoon Chung #include <asm-generic/errno.h> 15757bff49SJaehoon Chung 16757bff49SJaehoon Chung #define PAGE_SIZE 4096 17757bff49SJaehoon Chung 18757bff49SJaehoon Chung static int dwmci_wait_reset(struct dwmci_host *host, u32 value) 19757bff49SJaehoon Chung { 20757bff49SJaehoon Chung unsigned long timeout = 1000; 21757bff49SJaehoon Chung u32 ctrl; 22757bff49SJaehoon Chung 23757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CTRL, value); 24757bff49SJaehoon Chung 25757bff49SJaehoon Chung while (timeout--) { 26757bff49SJaehoon Chung ctrl = dwmci_readl(host, DWMCI_CTRL); 27757bff49SJaehoon Chung if (!(ctrl & DWMCI_RESET_ALL)) 28757bff49SJaehoon Chung return 1; 29757bff49SJaehoon Chung } 30757bff49SJaehoon Chung return 0; 31757bff49SJaehoon Chung } 32757bff49SJaehoon Chung 33757bff49SJaehoon Chung static void dwmci_set_idma_desc(struct dwmci_idmac *idmac, 34757bff49SJaehoon Chung u32 desc0, u32 desc1, u32 desc2) 35757bff49SJaehoon Chung { 36757bff49SJaehoon Chung struct dwmci_idmac *desc = idmac; 37757bff49SJaehoon Chung 38757bff49SJaehoon Chung desc->flags = desc0; 39757bff49SJaehoon Chung desc->cnt = desc1; 40757bff49SJaehoon Chung desc->addr = desc2; 41757bff49SJaehoon Chung desc->next_addr = (unsigned int)desc + sizeof(struct dwmci_idmac); 42757bff49SJaehoon Chung } 43757bff49SJaehoon Chung 44757bff49SJaehoon Chung static void dwmci_prepare_data(struct dwmci_host *host, 452a7a210eSAlexey Brodkin struct mmc_data *data, 462a7a210eSAlexey Brodkin struct dwmci_idmac *cur_idmac, 472a7a210eSAlexey Brodkin void *bounce_buffer) 48757bff49SJaehoon Chung { 49757bff49SJaehoon Chung unsigned long ctrl; 50757bff49SJaehoon Chung unsigned int i = 0, flags, cnt, blk_cnt; 512a7a210eSAlexey Brodkin ulong data_start, data_end; 52757bff49SJaehoon Chung 53757bff49SJaehoon Chung 54757bff49SJaehoon Chung blk_cnt = data->blocks; 55757bff49SJaehoon Chung 56757bff49SJaehoon Chung dwmci_wait_reset(host, DWMCI_CTRL_FIFO_RESET); 57757bff49SJaehoon Chung 58757bff49SJaehoon Chung data_start = (ulong)cur_idmac; 59757bff49SJaehoon Chung dwmci_writel(host, DWMCI_DBADDR, (unsigned int)cur_idmac); 60757bff49SJaehoon Chung 61757bff49SJaehoon Chung do { 62757bff49SJaehoon Chung flags = DWMCI_IDMAC_OWN | DWMCI_IDMAC_CH ; 63757bff49SJaehoon Chung flags |= (i == 0) ? DWMCI_IDMAC_FS : 0; 64757bff49SJaehoon Chung if (blk_cnt <= 8) { 65757bff49SJaehoon Chung flags |= DWMCI_IDMAC_LD; 66757bff49SJaehoon Chung cnt = data->blocksize * blk_cnt; 67757bff49SJaehoon Chung } else 68757bff49SJaehoon Chung cnt = data->blocksize * 8; 69757bff49SJaehoon Chung 70757bff49SJaehoon Chung dwmci_set_idma_desc(cur_idmac, flags, cnt, 712a7a210eSAlexey Brodkin (u32)bounce_buffer + (i * PAGE_SIZE)); 72757bff49SJaehoon Chung 7321bd5761SMischa Jonker if (blk_cnt <= 8) 74757bff49SJaehoon Chung break; 75757bff49SJaehoon Chung blk_cnt -= 8; 76757bff49SJaehoon Chung cur_idmac++; 77757bff49SJaehoon Chung i++; 78757bff49SJaehoon Chung } while(1); 79757bff49SJaehoon Chung 80757bff49SJaehoon Chung data_end = (ulong)cur_idmac; 81757bff49SJaehoon Chung flush_dcache_range(data_start, data_end + ARCH_DMA_MINALIGN); 82757bff49SJaehoon Chung 83757bff49SJaehoon Chung ctrl = dwmci_readl(host, DWMCI_CTRL); 84757bff49SJaehoon Chung ctrl |= DWMCI_IDMAC_EN | DWMCI_DMA_EN; 85757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CTRL, ctrl); 86757bff49SJaehoon Chung 87757bff49SJaehoon Chung ctrl = dwmci_readl(host, DWMCI_BMOD); 88757bff49SJaehoon Chung ctrl |= DWMCI_BMOD_IDMAC_FB | DWMCI_BMOD_IDMAC_EN; 89757bff49SJaehoon Chung dwmci_writel(host, DWMCI_BMOD, ctrl); 90757bff49SJaehoon Chung 91757bff49SJaehoon Chung dwmci_writel(host, DWMCI_BLKSIZ, data->blocksize); 92757bff49SJaehoon Chung dwmci_writel(host, DWMCI_BYTCNT, data->blocksize * data->blocks); 93757bff49SJaehoon Chung } 94757bff49SJaehoon Chung 95757bff49SJaehoon Chung static int dwmci_set_transfer_mode(struct dwmci_host *host, 96757bff49SJaehoon Chung struct mmc_data *data) 97757bff49SJaehoon Chung { 98757bff49SJaehoon Chung unsigned long mode; 99757bff49SJaehoon Chung 100757bff49SJaehoon Chung mode = DWMCI_CMD_DATA_EXP; 101757bff49SJaehoon Chung if (data->flags & MMC_DATA_WRITE) 102757bff49SJaehoon Chung mode |= DWMCI_CMD_RW; 103757bff49SJaehoon Chung 104757bff49SJaehoon Chung return mode; 105757bff49SJaehoon Chung } 106757bff49SJaehoon Chung 107757bff49SJaehoon Chung static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, 108757bff49SJaehoon Chung struct mmc_data *data) 109757bff49SJaehoon Chung { 11093bfd616SPantelis Antoniou struct dwmci_host *host = mmc->priv; 1112136d226SMischa Jonker ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac, 11221bd5761SMischa Jonker data ? DIV_ROUND_UP(data->blocks, 8) : 0); 113757bff49SJaehoon Chung int flags = 0, i; 114757bff49SJaehoon Chung unsigned int timeout = 100000; 115757bff49SJaehoon Chung u32 retry = 10000; 116757bff49SJaehoon Chung u32 mask, ctrl; 1179c50e35fSAmar ulong start = get_timer(0); 1182a7a210eSAlexey Brodkin struct bounce_buffer bbstate; 119757bff49SJaehoon Chung 120757bff49SJaehoon Chung while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) { 1219c50e35fSAmar if (get_timer(start) > timeout) { 122757bff49SJaehoon Chung printf("Timeout on data busy\n"); 123757bff49SJaehoon Chung return TIMEOUT; 124757bff49SJaehoon Chung } 125757bff49SJaehoon Chung } 126757bff49SJaehoon Chung 127757bff49SJaehoon Chung dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL); 128757bff49SJaehoon Chung 1292a7a210eSAlexey Brodkin if (data) { 1302a7a210eSAlexey Brodkin if (data->flags == MMC_DATA_READ) { 1312a7a210eSAlexey Brodkin bounce_buffer_start(&bbstate, (void*)data->dest, 1322a7a210eSAlexey Brodkin data->blocksize * 1332a7a210eSAlexey Brodkin data->blocks, GEN_BB_WRITE); 1342a7a210eSAlexey Brodkin } else { 1352a7a210eSAlexey Brodkin bounce_buffer_start(&bbstate, (void*)data->src, 1362a7a210eSAlexey Brodkin data->blocksize * 1372a7a210eSAlexey Brodkin data->blocks, GEN_BB_READ); 1382a7a210eSAlexey Brodkin } 1392a7a210eSAlexey Brodkin dwmci_prepare_data(host, data, cur_idmac, 1402a7a210eSAlexey Brodkin bbstate.bounce_buffer); 1412a7a210eSAlexey Brodkin } 142757bff49SJaehoon Chung 143757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CMDARG, cmd->cmdarg); 144757bff49SJaehoon Chung 145757bff49SJaehoon Chung if (data) 146757bff49SJaehoon Chung flags = dwmci_set_transfer_mode(host, data); 147757bff49SJaehoon Chung 148757bff49SJaehoon Chung if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type & MMC_RSP_BUSY)) 149757bff49SJaehoon Chung return -1; 150757bff49SJaehoon Chung 151757bff49SJaehoon Chung if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) 152757bff49SJaehoon Chung flags |= DWMCI_CMD_ABORT_STOP; 153757bff49SJaehoon Chung else 154757bff49SJaehoon Chung flags |= DWMCI_CMD_PRV_DAT_WAIT; 155757bff49SJaehoon Chung 156757bff49SJaehoon Chung if (cmd->resp_type & MMC_RSP_PRESENT) { 157757bff49SJaehoon Chung flags |= DWMCI_CMD_RESP_EXP; 158757bff49SJaehoon Chung if (cmd->resp_type & MMC_RSP_136) 159757bff49SJaehoon Chung flags |= DWMCI_CMD_RESP_LENGTH; 160757bff49SJaehoon Chung } 161757bff49SJaehoon Chung 162757bff49SJaehoon Chung if (cmd->resp_type & MMC_RSP_CRC) 163757bff49SJaehoon Chung flags |= DWMCI_CMD_CHECK_CRC; 164757bff49SJaehoon Chung 165757bff49SJaehoon Chung flags |= (cmd->cmdidx | DWMCI_CMD_START | DWMCI_CMD_USE_HOLD_REG); 166757bff49SJaehoon Chung 167757bff49SJaehoon Chung debug("Sending CMD%d\n",cmd->cmdidx); 168757bff49SJaehoon Chung 169757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CMD, flags); 170757bff49SJaehoon Chung 171757bff49SJaehoon Chung for (i = 0; i < retry; i++) { 172757bff49SJaehoon Chung mask = dwmci_readl(host, DWMCI_RINTSTS); 173757bff49SJaehoon Chung if (mask & DWMCI_INTMSK_CDONE) { 174757bff49SJaehoon Chung if (!data) 175757bff49SJaehoon Chung dwmci_writel(host, DWMCI_RINTSTS, mask); 176757bff49SJaehoon Chung break; 177757bff49SJaehoon Chung } 178757bff49SJaehoon Chung } 179757bff49SJaehoon Chung 180757bff49SJaehoon Chung if (i == retry) 181757bff49SJaehoon Chung return TIMEOUT; 182757bff49SJaehoon Chung 183757bff49SJaehoon Chung if (mask & DWMCI_INTMSK_RTO) { 184757bff49SJaehoon Chung debug("Response Timeout..\n"); 185757bff49SJaehoon Chung return TIMEOUT; 186757bff49SJaehoon Chung } else if (mask & DWMCI_INTMSK_RE) { 187757bff49SJaehoon Chung debug("Response Error..\n"); 188757bff49SJaehoon Chung return -1; 189757bff49SJaehoon Chung } 190757bff49SJaehoon Chung 191757bff49SJaehoon Chung 192757bff49SJaehoon Chung if (cmd->resp_type & MMC_RSP_PRESENT) { 193757bff49SJaehoon Chung if (cmd->resp_type & MMC_RSP_136) { 194757bff49SJaehoon Chung cmd->response[0] = dwmci_readl(host, DWMCI_RESP3); 195757bff49SJaehoon Chung cmd->response[1] = dwmci_readl(host, DWMCI_RESP2); 196757bff49SJaehoon Chung cmd->response[2] = dwmci_readl(host, DWMCI_RESP1); 197757bff49SJaehoon Chung cmd->response[3] = dwmci_readl(host, DWMCI_RESP0); 198757bff49SJaehoon Chung } else { 199757bff49SJaehoon Chung cmd->response[0] = dwmci_readl(host, DWMCI_RESP0); 200757bff49SJaehoon Chung } 201757bff49SJaehoon Chung } 202757bff49SJaehoon Chung 203757bff49SJaehoon Chung if (data) { 204757bff49SJaehoon Chung do { 205757bff49SJaehoon Chung mask = dwmci_readl(host, DWMCI_RINTSTS); 206757bff49SJaehoon Chung if (mask & (DWMCI_DATA_ERR | DWMCI_DATA_TOUT)) { 207757bff49SJaehoon Chung debug("DATA ERROR!\n"); 208757bff49SJaehoon Chung return -1; 209757bff49SJaehoon Chung } 210757bff49SJaehoon Chung } while (!(mask & DWMCI_INTMSK_DTO)); 211757bff49SJaehoon Chung 212757bff49SJaehoon Chung dwmci_writel(host, DWMCI_RINTSTS, mask); 213757bff49SJaehoon Chung 214757bff49SJaehoon Chung ctrl = dwmci_readl(host, DWMCI_CTRL); 215757bff49SJaehoon Chung ctrl &= ~(DWMCI_DMA_EN); 216757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CTRL, ctrl); 2172a7a210eSAlexey Brodkin 2182a7a210eSAlexey Brodkin bounce_buffer_stop(&bbstate); 219757bff49SJaehoon Chung } 220757bff49SJaehoon Chung 221757bff49SJaehoon Chung udelay(100); 222757bff49SJaehoon Chung 223757bff49SJaehoon Chung return 0; 224757bff49SJaehoon Chung } 225757bff49SJaehoon Chung 226757bff49SJaehoon Chung static int dwmci_setup_bus(struct dwmci_host *host, u32 freq) 227757bff49SJaehoon Chung { 228757bff49SJaehoon Chung u32 div, status; 229757bff49SJaehoon Chung int timeout = 10000; 230757bff49SJaehoon Chung unsigned long sclk; 231757bff49SJaehoon Chung 2329c50e35fSAmar if ((freq == host->clock) || (freq == 0)) 233757bff49SJaehoon Chung return 0; 234757bff49SJaehoon Chung /* 235b44fe83aSJaehoon Chung * If host->get_mmc_clk didn't define, 236757bff49SJaehoon Chung * then assume that host->bus_hz is source clock value. 237757bff49SJaehoon Chung * host->bus_hz should be set from user. 238757bff49SJaehoon Chung */ 239b44fe83aSJaehoon Chung if (host->get_mmc_clk) 240d3e016ccSRajeshwari S Shinde sclk = host->get_mmc_clk(host); 241757bff49SJaehoon Chung else if (host->bus_hz) 242757bff49SJaehoon Chung sclk = host->bus_hz; 243757bff49SJaehoon Chung else { 244757bff49SJaehoon Chung printf("Didn't get source clock value..\n"); 245757bff49SJaehoon Chung return -EINVAL; 246757bff49SJaehoon Chung } 247757bff49SJaehoon Chung 248757bff49SJaehoon Chung div = DIV_ROUND_UP(sclk, 2 * freq); 249757bff49SJaehoon Chung 250757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CLKENA, 0); 251757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CLKSRC, 0); 252757bff49SJaehoon Chung 253757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CLKDIV, div); 254757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT | 255757bff49SJaehoon Chung DWMCI_CMD_UPD_CLK | DWMCI_CMD_START); 256757bff49SJaehoon Chung 257757bff49SJaehoon Chung do { 258757bff49SJaehoon Chung status = dwmci_readl(host, DWMCI_CMD); 259757bff49SJaehoon Chung if (timeout-- < 0) { 260757bff49SJaehoon Chung printf("TIMEOUT error!!\n"); 261757bff49SJaehoon Chung return -ETIMEDOUT; 262757bff49SJaehoon Chung } 263757bff49SJaehoon Chung } while (status & DWMCI_CMD_START); 264757bff49SJaehoon Chung 265757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CLKENA, DWMCI_CLKEN_ENABLE | 266757bff49SJaehoon Chung DWMCI_CLKEN_LOW_PWR); 267757bff49SJaehoon Chung 268757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT | 269757bff49SJaehoon Chung DWMCI_CMD_UPD_CLK | DWMCI_CMD_START); 270757bff49SJaehoon Chung 271757bff49SJaehoon Chung timeout = 10000; 272757bff49SJaehoon Chung do { 273757bff49SJaehoon Chung status = dwmci_readl(host, DWMCI_CMD); 274757bff49SJaehoon Chung if (timeout-- < 0) { 275757bff49SJaehoon Chung printf("TIMEOUT error!!\n"); 276757bff49SJaehoon Chung return -ETIMEDOUT; 277757bff49SJaehoon Chung } 278757bff49SJaehoon Chung } while (status & DWMCI_CMD_START); 279757bff49SJaehoon Chung 280757bff49SJaehoon Chung host->clock = freq; 281757bff49SJaehoon Chung 282757bff49SJaehoon Chung return 0; 283757bff49SJaehoon Chung } 284757bff49SJaehoon Chung 285757bff49SJaehoon Chung static void dwmci_set_ios(struct mmc *mmc) 286757bff49SJaehoon Chung { 287*045bdcd0SJaehoon Chung struct dwmci_host *host = (struct dwmci_host *)mmc->priv; 288*045bdcd0SJaehoon Chung u32 ctype, regs; 289757bff49SJaehoon Chung 290757bff49SJaehoon Chung debug("Buswidth = %d, clock: %d\n",mmc->bus_width, mmc->clock); 291757bff49SJaehoon Chung 292757bff49SJaehoon Chung dwmci_setup_bus(host, mmc->clock); 293757bff49SJaehoon Chung switch (mmc->bus_width) { 294757bff49SJaehoon Chung case 8: 295757bff49SJaehoon Chung ctype = DWMCI_CTYPE_8BIT; 296757bff49SJaehoon Chung break; 297757bff49SJaehoon Chung case 4: 298757bff49SJaehoon Chung ctype = DWMCI_CTYPE_4BIT; 299757bff49SJaehoon Chung break; 300757bff49SJaehoon Chung default: 301757bff49SJaehoon Chung ctype = DWMCI_CTYPE_1BIT; 302757bff49SJaehoon Chung break; 303757bff49SJaehoon Chung } 304757bff49SJaehoon Chung 305757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CTYPE, ctype); 306757bff49SJaehoon Chung 307*045bdcd0SJaehoon Chung regs = dwmci_readl(host, DWMCI_UHS_REG); 308*045bdcd0SJaehoon Chung if (mmc->card_caps & MMC_MODE_DDR_52MHz) 309*045bdcd0SJaehoon Chung regs |= DWMCI_DDR_MODE; 310*045bdcd0SJaehoon Chung else 311*045bdcd0SJaehoon Chung regs &= DWMCI_DDR_MODE; 312*045bdcd0SJaehoon Chung 313*045bdcd0SJaehoon Chung dwmci_writel(host, DWMCI_UHS_REG, regs); 314*045bdcd0SJaehoon Chung 315757bff49SJaehoon Chung if (host->clksel) 316757bff49SJaehoon Chung host->clksel(host); 317757bff49SJaehoon Chung } 318757bff49SJaehoon Chung 319757bff49SJaehoon Chung static int dwmci_init(struct mmc *mmc) 320757bff49SJaehoon Chung { 32193bfd616SPantelis Antoniou struct dwmci_host *host = mmc->priv; 322757bff49SJaehoon Chung 32318ab6755SJaehoon Chung if (host->board_init) 32418ab6755SJaehoon Chung host->board_init(host); 3256f0b7caaSRajeshwari Shinde 326757bff49SJaehoon Chung dwmci_writel(host, DWMCI_PWREN, 1); 327757bff49SJaehoon Chung 328757bff49SJaehoon Chung if (!dwmci_wait_reset(host, DWMCI_RESET_ALL)) { 329757bff49SJaehoon Chung debug("%s[%d] Fail-reset!!\n",__func__,__LINE__); 330757bff49SJaehoon Chung return -1; 331757bff49SJaehoon Chung } 332757bff49SJaehoon Chung 3339c50e35fSAmar /* Enumerate at 400KHz */ 33493bfd616SPantelis Antoniou dwmci_setup_bus(host, mmc->cfg->f_min); 3359c50e35fSAmar 336757bff49SJaehoon Chung dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF); 337757bff49SJaehoon Chung dwmci_writel(host, DWMCI_INTMASK, 0); 338757bff49SJaehoon Chung 339757bff49SJaehoon Chung dwmci_writel(host, DWMCI_TMOUT, 0xFFFFFFFF); 340757bff49SJaehoon Chung 341757bff49SJaehoon Chung dwmci_writel(host, DWMCI_IDINTEN, 0); 342757bff49SJaehoon Chung dwmci_writel(host, DWMCI_BMOD, 1); 343757bff49SJaehoon Chung 3449108b315SAlexey Brodkin if (host->fifoth_val) { 345ed7bdc03SRajeshwari Shinde dwmci_writel(host, DWMCI_FIFOTH, host->fifoth_val); 3469108b315SAlexey Brodkin } 347757bff49SJaehoon Chung 348757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CLKENA, 0); 349757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CLKSRC, 0); 350757bff49SJaehoon Chung 351757bff49SJaehoon Chung return 0; 352757bff49SJaehoon Chung } 353757bff49SJaehoon Chung 354ab769f22SPantelis Antoniou static const struct mmc_ops dwmci_ops = { 355ab769f22SPantelis Antoniou .send_cmd = dwmci_send_cmd, 356ab769f22SPantelis Antoniou .set_ios = dwmci_set_ios, 357ab769f22SPantelis Antoniou .init = dwmci_init, 358ab769f22SPantelis Antoniou }; 359ab769f22SPantelis Antoniou 360757bff49SJaehoon Chung int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk) 361757bff49SJaehoon Chung { 36293bfd616SPantelis Antoniou host->cfg.name = host->name; 36393bfd616SPantelis Antoniou host->cfg.ops = &dwmci_ops; 36493bfd616SPantelis Antoniou host->cfg.f_min = min_clk; 36593bfd616SPantelis Antoniou host->cfg.f_max = max_clk; 366757bff49SJaehoon Chung 36793bfd616SPantelis Antoniou host->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; 368757bff49SJaehoon Chung 36993bfd616SPantelis Antoniou host->cfg.host_caps = host->caps; 370757bff49SJaehoon Chung 371757bff49SJaehoon Chung if (host->buswidth == 8) { 37293bfd616SPantelis Antoniou host->cfg.host_caps |= MMC_MODE_8BIT; 37393bfd616SPantelis Antoniou host->cfg.host_caps &= ~MMC_MODE_4BIT; 374757bff49SJaehoon Chung } else { 37593bfd616SPantelis Antoniou host->cfg.host_caps |= MMC_MODE_4BIT; 37693bfd616SPantelis Antoniou host->cfg.host_caps &= ~MMC_MODE_8BIT; 377757bff49SJaehoon Chung } 37893bfd616SPantelis Antoniou host->cfg.host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_HC; 379757bff49SJaehoon Chung 38093bfd616SPantelis Antoniou host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; 381757bff49SJaehoon Chung 38293bfd616SPantelis Antoniou host->mmc = mmc_create(&host->cfg, host); 38393bfd616SPantelis Antoniou if (host->mmc == NULL) 38493bfd616SPantelis Antoniou return -1; 38593bfd616SPantelis Antoniou 38693bfd616SPantelis Antoniou return 0; 387757bff49SJaehoon Chung } 388