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) { 122f33c9305SPavel Machek printf("%s: Timeout on data busy\n", __func__); 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 180f33c9305SPavel Machek if (i == retry) { 181f33c9305SPavel Machek printf("%s: Timeout.\n", __func__); 182757bff49SJaehoon Chung return TIMEOUT; 183f33c9305SPavel Machek } 184757bff49SJaehoon Chung 185757bff49SJaehoon Chung if (mask & DWMCI_INTMSK_RTO) { 186f33c9305SPavel Machek /* 187f33c9305SPavel Machek * Timeout here is not necessarily fatal. (e)MMC cards 188f33c9305SPavel Machek * will splat here when they receive CMD55 as they do 189f33c9305SPavel Machek * not support this command and that is exactly the way 190f33c9305SPavel Machek * to tell them apart from SD cards. Thus, this output 191f33c9305SPavel Machek * below shall be debug(). eMMC cards also do not favor 192f33c9305SPavel Machek * CMD8, please keep that in mind. 193f33c9305SPavel Machek */ 194f33c9305SPavel Machek debug("%s: Response Timeout.\n", __func__); 195757bff49SJaehoon Chung return TIMEOUT; 196757bff49SJaehoon Chung } else if (mask & DWMCI_INTMSK_RE) { 197f33c9305SPavel Machek printf("%s: Response Error.\n", __func__); 198757bff49SJaehoon Chung return -1; 199757bff49SJaehoon Chung } 200757bff49SJaehoon Chung 201757bff49SJaehoon Chung 202757bff49SJaehoon Chung if (cmd->resp_type & MMC_RSP_PRESENT) { 203757bff49SJaehoon Chung if (cmd->resp_type & MMC_RSP_136) { 204757bff49SJaehoon Chung cmd->response[0] = dwmci_readl(host, DWMCI_RESP3); 205757bff49SJaehoon Chung cmd->response[1] = dwmci_readl(host, DWMCI_RESP2); 206757bff49SJaehoon Chung cmd->response[2] = dwmci_readl(host, DWMCI_RESP1); 207757bff49SJaehoon Chung cmd->response[3] = dwmci_readl(host, DWMCI_RESP0); 208757bff49SJaehoon Chung } else { 209757bff49SJaehoon Chung cmd->response[0] = dwmci_readl(host, DWMCI_RESP0); 210757bff49SJaehoon Chung } 211757bff49SJaehoon Chung } 212757bff49SJaehoon Chung 213757bff49SJaehoon Chung if (data) { 214757bff49SJaehoon Chung do { 215757bff49SJaehoon Chung mask = dwmci_readl(host, DWMCI_RINTSTS); 216757bff49SJaehoon Chung if (mask & (DWMCI_DATA_ERR | DWMCI_DATA_TOUT)) { 217f33c9305SPavel Machek printf("%s: DATA ERROR!\n", __func__); 218757bff49SJaehoon Chung return -1; 219757bff49SJaehoon Chung } 220757bff49SJaehoon Chung } while (!(mask & DWMCI_INTMSK_DTO)); 221757bff49SJaehoon Chung 222757bff49SJaehoon Chung dwmci_writel(host, DWMCI_RINTSTS, mask); 223757bff49SJaehoon Chung 224757bff49SJaehoon Chung ctrl = dwmci_readl(host, DWMCI_CTRL); 225757bff49SJaehoon Chung ctrl &= ~(DWMCI_DMA_EN); 226757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CTRL, ctrl); 2272a7a210eSAlexey Brodkin 2282a7a210eSAlexey Brodkin bounce_buffer_stop(&bbstate); 229757bff49SJaehoon Chung } 230757bff49SJaehoon Chung 231757bff49SJaehoon Chung udelay(100); 232757bff49SJaehoon Chung 233757bff49SJaehoon Chung return 0; 234757bff49SJaehoon Chung } 235757bff49SJaehoon Chung 236757bff49SJaehoon Chung static int dwmci_setup_bus(struct dwmci_host *host, u32 freq) 237757bff49SJaehoon Chung { 238757bff49SJaehoon Chung u32 div, status; 239757bff49SJaehoon Chung int timeout = 10000; 240757bff49SJaehoon Chung unsigned long sclk; 241757bff49SJaehoon Chung 2429c50e35fSAmar if ((freq == host->clock) || (freq == 0)) 243757bff49SJaehoon Chung return 0; 244757bff49SJaehoon Chung /* 245f33c9305SPavel Machek * If host->get_mmc_clk isn't defined, 246757bff49SJaehoon Chung * then assume that host->bus_hz is source clock value. 247f33c9305SPavel Machek * host->bus_hz should be set by user. 248757bff49SJaehoon Chung */ 249b44fe83aSJaehoon Chung if (host->get_mmc_clk) 250d3e016ccSRajeshwari S Shinde sclk = host->get_mmc_clk(host); 251757bff49SJaehoon Chung else if (host->bus_hz) 252757bff49SJaehoon Chung sclk = host->bus_hz; 253757bff49SJaehoon Chung else { 254f33c9305SPavel Machek printf("%s: Didn't get source clock value.\n", __func__); 255757bff49SJaehoon Chung return -EINVAL; 256757bff49SJaehoon Chung } 257757bff49SJaehoon Chung 2586ace153dSChin Liang See if (sclk == freq) 2596ace153dSChin Liang See div = 0; /* bypass mode */ 2606ace153dSChin Liang See else 261757bff49SJaehoon Chung div = DIV_ROUND_UP(sclk, 2 * freq); 262757bff49SJaehoon Chung 263757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CLKENA, 0); 264757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CLKSRC, 0); 265757bff49SJaehoon Chung 266757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CLKDIV, div); 267757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT | 268757bff49SJaehoon Chung DWMCI_CMD_UPD_CLK | DWMCI_CMD_START); 269757bff49SJaehoon Chung 270757bff49SJaehoon Chung do { 271757bff49SJaehoon Chung status = dwmci_readl(host, DWMCI_CMD); 272757bff49SJaehoon Chung if (timeout-- < 0) { 273f33c9305SPavel Machek printf("%s: Timeout!\n", __func__); 274757bff49SJaehoon Chung return -ETIMEDOUT; 275757bff49SJaehoon Chung } 276757bff49SJaehoon Chung } while (status & DWMCI_CMD_START); 277757bff49SJaehoon Chung 278757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CLKENA, DWMCI_CLKEN_ENABLE | 279757bff49SJaehoon Chung DWMCI_CLKEN_LOW_PWR); 280757bff49SJaehoon Chung 281757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT | 282757bff49SJaehoon Chung DWMCI_CMD_UPD_CLK | DWMCI_CMD_START); 283757bff49SJaehoon Chung 284757bff49SJaehoon Chung timeout = 10000; 285757bff49SJaehoon Chung do { 286757bff49SJaehoon Chung status = dwmci_readl(host, DWMCI_CMD); 287757bff49SJaehoon Chung if (timeout-- < 0) { 288f33c9305SPavel Machek printf("%s: Timeout!\n", __func__); 289757bff49SJaehoon Chung return -ETIMEDOUT; 290757bff49SJaehoon Chung } 291757bff49SJaehoon Chung } while (status & DWMCI_CMD_START); 292757bff49SJaehoon Chung 293757bff49SJaehoon Chung host->clock = freq; 294757bff49SJaehoon Chung 295757bff49SJaehoon Chung return 0; 296757bff49SJaehoon Chung } 297757bff49SJaehoon Chung 298757bff49SJaehoon Chung static void dwmci_set_ios(struct mmc *mmc) 299757bff49SJaehoon Chung { 300045bdcd0SJaehoon Chung struct dwmci_host *host = (struct dwmci_host *)mmc->priv; 301045bdcd0SJaehoon Chung u32 ctype, regs; 302757bff49SJaehoon Chung 303757bff49SJaehoon Chung debug("Buswidth = %d, clock: %d\n", mmc->bus_width, mmc->clock); 304757bff49SJaehoon Chung 305757bff49SJaehoon Chung dwmci_setup_bus(host, mmc->clock); 306757bff49SJaehoon Chung switch (mmc->bus_width) { 307757bff49SJaehoon Chung case 8: 308757bff49SJaehoon Chung ctype = DWMCI_CTYPE_8BIT; 309757bff49SJaehoon Chung break; 310757bff49SJaehoon Chung case 4: 311757bff49SJaehoon Chung ctype = DWMCI_CTYPE_4BIT; 312757bff49SJaehoon Chung break; 313757bff49SJaehoon Chung default: 314757bff49SJaehoon Chung ctype = DWMCI_CTYPE_1BIT; 315757bff49SJaehoon Chung break; 316757bff49SJaehoon Chung } 317757bff49SJaehoon Chung 318757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CTYPE, ctype); 319757bff49SJaehoon Chung 320045bdcd0SJaehoon Chung regs = dwmci_readl(host, DWMCI_UHS_REG); 321*2b8a9692SAndrew Gabbasov if (mmc->ddr_mode) 322045bdcd0SJaehoon Chung regs |= DWMCI_DDR_MODE; 323045bdcd0SJaehoon Chung else 324045bdcd0SJaehoon Chung regs &= DWMCI_DDR_MODE; 325045bdcd0SJaehoon Chung 326045bdcd0SJaehoon Chung dwmci_writel(host, DWMCI_UHS_REG, regs); 327045bdcd0SJaehoon Chung 328757bff49SJaehoon Chung if (host->clksel) 329757bff49SJaehoon Chung host->clksel(host); 330757bff49SJaehoon Chung } 331757bff49SJaehoon Chung 332757bff49SJaehoon Chung static int dwmci_init(struct mmc *mmc) 333757bff49SJaehoon Chung { 33493bfd616SPantelis Antoniou struct dwmci_host *host = mmc->priv; 335757bff49SJaehoon Chung 33618ab6755SJaehoon Chung if (host->board_init) 33718ab6755SJaehoon Chung host->board_init(host); 3386f0b7caaSRajeshwari Shinde 339757bff49SJaehoon Chung dwmci_writel(host, DWMCI_PWREN, 1); 340757bff49SJaehoon Chung 341757bff49SJaehoon Chung if (!dwmci_wait_reset(host, DWMCI_RESET_ALL)) { 342f33c9305SPavel Machek printf("%s[%d] Fail-reset!!\n", __func__, __LINE__); 343757bff49SJaehoon Chung return -1; 344757bff49SJaehoon Chung } 345757bff49SJaehoon Chung 3469c50e35fSAmar /* Enumerate at 400KHz */ 34793bfd616SPantelis Antoniou dwmci_setup_bus(host, mmc->cfg->f_min); 3489c50e35fSAmar 349757bff49SJaehoon Chung dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF); 350757bff49SJaehoon Chung dwmci_writel(host, DWMCI_INTMASK, 0); 351757bff49SJaehoon Chung 352757bff49SJaehoon Chung dwmci_writel(host, DWMCI_TMOUT, 0xFFFFFFFF); 353757bff49SJaehoon Chung 354757bff49SJaehoon Chung dwmci_writel(host, DWMCI_IDINTEN, 0); 355757bff49SJaehoon Chung dwmci_writel(host, DWMCI_BMOD, 1); 356757bff49SJaehoon Chung 3579108b315SAlexey Brodkin if (host->fifoth_val) { 358ed7bdc03SRajeshwari Shinde dwmci_writel(host, DWMCI_FIFOTH, host->fifoth_val); 3599108b315SAlexey Brodkin } 360757bff49SJaehoon Chung 361757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CLKENA, 0); 362757bff49SJaehoon Chung dwmci_writel(host, DWMCI_CLKSRC, 0); 363757bff49SJaehoon Chung 364757bff49SJaehoon Chung return 0; 365757bff49SJaehoon Chung } 366757bff49SJaehoon Chung 367ab769f22SPantelis Antoniou static const struct mmc_ops dwmci_ops = { 368ab769f22SPantelis Antoniou .send_cmd = dwmci_send_cmd, 369ab769f22SPantelis Antoniou .set_ios = dwmci_set_ios, 370ab769f22SPantelis Antoniou .init = dwmci_init, 371ab769f22SPantelis Antoniou }; 372ab769f22SPantelis Antoniou 373757bff49SJaehoon Chung int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk) 374757bff49SJaehoon Chung { 37593bfd616SPantelis Antoniou host->cfg.name = host->name; 37693bfd616SPantelis Antoniou host->cfg.ops = &dwmci_ops; 37793bfd616SPantelis Antoniou host->cfg.f_min = min_clk; 37893bfd616SPantelis Antoniou host->cfg.f_max = max_clk; 379757bff49SJaehoon Chung 38093bfd616SPantelis Antoniou host->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; 381757bff49SJaehoon Chung 38293bfd616SPantelis Antoniou host->cfg.host_caps = host->caps; 383757bff49SJaehoon Chung 384757bff49SJaehoon Chung if (host->buswidth == 8) { 38593bfd616SPantelis Antoniou host->cfg.host_caps |= MMC_MODE_8BIT; 38693bfd616SPantelis Antoniou host->cfg.host_caps &= ~MMC_MODE_4BIT; 387757bff49SJaehoon Chung } else { 38893bfd616SPantelis Antoniou host->cfg.host_caps |= MMC_MODE_4BIT; 38993bfd616SPantelis Antoniou host->cfg.host_caps &= ~MMC_MODE_8BIT; 390757bff49SJaehoon Chung } 39193bfd616SPantelis Antoniou host->cfg.host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_HC; 392757bff49SJaehoon Chung 39393bfd616SPantelis Antoniou host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; 394757bff49SJaehoon Chung 39593bfd616SPantelis Antoniou host->mmc = mmc_create(&host->cfg, host); 39693bfd616SPantelis Antoniou if (host->mmc == NULL) 39793bfd616SPantelis Antoniou return -1; 39893bfd616SPantelis Antoniou 39993bfd616SPantelis Antoniou return 0; 400757bff49SJaehoon Chung } 401