1de941241SSukumar Ghorai /* 2de941241SSukumar Ghorai * (C) Copyright 2008 3de941241SSukumar Ghorai * Texas Instruments, <www.ti.com> 4de941241SSukumar Ghorai * Sukumar Ghorai <s-ghorai@ti.com> 5de941241SSukumar Ghorai * 6de941241SSukumar Ghorai * See file CREDITS for list of people who contributed to this 7de941241SSukumar Ghorai * project. 8de941241SSukumar Ghorai * 9de941241SSukumar Ghorai * This program is free software; you can redistribute it and/or 10de941241SSukumar Ghorai * modify it under the terms of the GNU General Public License as 11de941241SSukumar Ghorai * published by the Free Software Foundation's version 2 of 12de941241SSukumar Ghorai * the License. 13de941241SSukumar Ghorai * 14de941241SSukumar Ghorai * This program is distributed in the hope that it will be useful, 15de941241SSukumar Ghorai * but WITHOUT ANY WARRANTY; without even the implied warranty of 16de941241SSukumar Ghorai * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17de941241SSukumar Ghorai * GNU General Public License for more details. 18de941241SSukumar Ghorai * 19de941241SSukumar Ghorai * You should have received a copy of the GNU General Public License 20de941241SSukumar Ghorai * along with this program; if not, write to the Free Software 21de941241SSukumar Ghorai * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 22de941241SSukumar Ghorai * MA 02111-1307 USA 23de941241SSukumar Ghorai */ 24de941241SSukumar Ghorai 25de941241SSukumar Ghorai #include <config.h> 26de941241SSukumar Ghorai #include <common.h> 27de941241SSukumar Ghorai #include <mmc.h> 28de941241SSukumar Ghorai #include <part.h> 29de941241SSukumar Ghorai #include <i2c.h> 30de941241SSukumar Ghorai #include <twl4030.h> 3114fa2dd0SBalaji T K #include <twl6030.h> 32de941241SSukumar Ghorai #include <asm/io.h> 33de941241SSukumar Ghorai #include <asm/arch/mmc_host_def.h> 3496e0e7b3SDirk Behme #include <asm/arch/sys_proto.h> 35de941241SSukumar Ghorai 36eb9a28f6SNishanth Menon /* If we fail after 1 second wait, something is really bad */ 37eb9a28f6SNishanth Menon #define MAX_RETRY_MS 1000 38eb9a28f6SNishanth Menon 39de941241SSukumar Ghorai static int mmc_read_data(hsmmc_t *mmc_base, char *buf, unsigned int size); 40de941241SSukumar Ghorai static int mmc_write_data(hsmmc_t *mmc_base, const char *buf, unsigned int siz); 41de941241SSukumar Ghorai static struct mmc hsmmc_dev[2]; 4214fa2dd0SBalaji T K 4314fa2dd0SBalaji T K #if defined(CONFIG_OMAP44XX) && defined(CONFIG_TWL6030_POWER) 4414fa2dd0SBalaji T K static void omap4_vmmc_pbias_config(struct mmc *mmc) 4514fa2dd0SBalaji T K { 4614fa2dd0SBalaji T K u32 value = 0; 4714fa2dd0SBalaji T K struct omap4_sys_ctrl_regs *const ctrl = 4814fa2dd0SBalaji T K (struct omap4_sys_ctrl_regs *)SYSCTRL_GENERAL_CORE_BASE; 4914fa2dd0SBalaji T K 5014fa2dd0SBalaji T K 5114fa2dd0SBalaji T K value = readl(&ctrl->control_pbiaslite); 5214fa2dd0SBalaji T K value &= ~(MMC1_PBIASLITE_PWRDNZ | MMC1_PWRDNZ); 5314fa2dd0SBalaji T K writel(value, &ctrl->control_pbiaslite); 5414fa2dd0SBalaji T K /* set VMMC to 3V */ 5514fa2dd0SBalaji T K twl6030_power_mmc_init(); 5614fa2dd0SBalaji T K value = readl(&ctrl->control_pbiaslite); 5714fa2dd0SBalaji T K value |= MMC1_PBIASLITE_VMODE | MMC1_PBIASLITE_PWRDNZ | MMC1_PWRDNZ; 5814fa2dd0SBalaji T K writel(value, &ctrl->control_pbiaslite); 5914fa2dd0SBalaji T K } 6014fa2dd0SBalaji T K #endif 6114fa2dd0SBalaji T K 6214fa2dd0SBalaji T K unsigned char mmc_board_init(struct mmc *mmc) 63de941241SSukumar Ghorai { 64de941241SSukumar Ghorai #if defined(CONFIG_TWL4030_POWER) 65de941241SSukumar Ghorai twl4030_power_mmc_init(); 66de941241SSukumar Ghorai #endif 67de941241SSukumar Ghorai 68de941241SSukumar Ghorai #if defined(CONFIG_OMAP34XX) 69de941241SSukumar Ghorai t2_t *t2_base = (t2_t *)T2_BASE; 70de941241SSukumar Ghorai struct prcm *prcm_base = (struct prcm *)PRCM_BASE; 71de941241SSukumar Ghorai 72de941241SSukumar Ghorai writel(readl(&t2_base->pbias_lite) | PBIASLITEPWRDNZ1 | 73de941241SSukumar Ghorai PBIASSPEEDCTRL0 | PBIASLITEPWRDNZ0, 74de941241SSukumar Ghorai &t2_base->pbias_lite); 75de941241SSukumar Ghorai 76de941241SSukumar Ghorai writel(readl(&t2_base->devconf0) | MMCSDIO1ADPCLKISEL, 77de941241SSukumar Ghorai &t2_base->devconf0); 78de941241SSukumar Ghorai 79de941241SSukumar Ghorai writel(readl(&t2_base->devconf1) | MMCSDIO2ADPCLKISEL, 80de941241SSukumar Ghorai &t2_base->devconf1); 81de941241SSukumar Ghorai 82de941241SSukumar Ghorai writel(readl(&prcm_base->fclken1_core) | 83de941241SSukumar Ghorai EN_MMC1 | EN_MMC2 | EN_MMC3, 84de941241SSukumar Ghorai &prcm_base->fclken1_core); 85de941241SSukumar Ghorai 86de941241SSukumar Ghorai writel(readl(&prcm_base->iclken1_core) | 87de941241SSukumar Ghorai EN_MMC1 | EN_MMC2 | EN_MMC3, 88de941241SSukumar Ghorai &prcm_base->iclken1_core); 89de941241SSukumar Ghorai #endif 90de941241SSukumar Ghorai 9114fa2dd0SBalaji T K #if defined(CONFIG_OMAP44XX) && defined(CONFIG_TWL6030_POWER) 9214fa2dd0SBalaji T K /* PBIAS config needed for MMC1 only */ 9314fa2dd0SBalaji T K if (mmc->block_dev.dev == 0) 9414fa2dd0SBalaji T K omap4_vmmc_pbias_config(mmc); 9514fa2dd0SBalaji T K #endif 96de941241SSukumar Ghorai 97de941241SSukumar Ghorai return 0; 98de941241SSukumar Ghorai } 99de941241SSukumar Ghorai 100de941241SSukumar Ghorai void mmc_init_stream(hsmmc_t *mmc_base) 101de941241SSukumar Ghorai { 102eb9a28f6SNishanth Menon ulong start; 103de941241SSukumar Ghorai 104de941241SSukumar Ghorai writel(readl(&mmc_base->con) | INIT_INITSTREAM, &mmc_base->con); 105de941241SSukumar Ghorai 106de941241SSukumar Ghorai writel(MMC_CMD0, &mmc_base->cmd); 107eb9a28f6SNishanth Menon start = get_timer(0); 108eb9a28f6SNishanth Menon while (!(readl(&mmc_base->stat) & CC_MASK)) { 109eb9a28f6SNishanth Menon if (get_timer(0) - start > MAX_RETRY_MS) { 110eb9a28f6SNishanth Menon printf("%s: timedout waiting for cc!\n", __func__); 111eb9a28f6SNishanth Menon return; 112eb9a28f6SNishanth Menon } 113eb9a28f6SNishanth Menon } 114de941241SSukumar Ghorai writel(CC_MASK, &mmc_base->stat) 115de941241SSukumar Ghorai ; 116de941241SSukumar Ghorai writel(MMC_CMD0, &mmc_base->cmd) 117de941241SSukumar Ghorai ; 118eb9a28f6SNishanth Menon start = get_timer(0); 119eb9a28f6SNishanth Menon while (!(readl(&mmc_base->stat) & CC_MASK)) { 120eb9a28f6SNishanth Menon if (get_timer(0) - start > MAX_RETRY_MS) { 121eb9a28f6SNishanth Menon printf("%s: timedout waiting for cc2!\n", __func__); 122eb9a28f6SNishanth Menon return; 123eb9a28f6SNishanth Menon } 124eb9a28f6SNishanth Menon } 125de941241SSukumar Ghorai writel(readl(&mmc_base->con) & ~INIT_INITSTREAM, &mmc_base->con); 126de941241SSukumar Ghorai } 127de941241SSukumar Ghorai 128de941241SSukumar Ghorai 129de941241SSukumar Ghorai static int mmc_init_setup(struct mmc *mmc) 130de941241SSukumar Ghorai { 131de941241SSukumar Ghorai hsmmc_t *mmc_base = (hsmmc_t *)mmc->priv; 132de941241SSukumar Ghorai unsigned int reg_val; 133de941241SSukumar Ghorai unsigned int dsor; 134eb9a28f6SNishanth Menon ulong start; 135de941241SSukumar Ghorai 13614fa2dd0SBalaji T K mmc_board_init(mmc); 137de941241SSukumar Ghorai 138de941241SSukumar Ghorai writel(readl(&mmc_base->sysconfig) | MMC_SOFTRESET, 139de941241SSukumar Ghorai &mmc_base->sysconfig); 140eb9a28f6SNishanth Menon start = get_timer(0); 141eb9a28f6SNishanth Menon while ((readl(&mmc_base->sysstatus) & RESETDONE) == 0) { 142eb9a28f6SNishanth Menon if (get_timer(0) - start > MAX_RETRY_MS) { 143eb9a28f6SNishanth Menon printf("%s: timedout waiting for cc2!\n", __func__); 144eb9a28f6SNishanth Menon return TIMEOUT; 145eb9a28f6SNishanth Menon } 146eb9a28f6SNishanth Menon } 147de941241SSukumar Ghorai writel(readl(&mmc_base->sysctl) | SOFTRESETALL, &mmc_base->sysctl); 148eb9a28f6SNishanth Menon start = get_timer(0); 149eb9a28f6SNishanth Menon while ((readl(&mmc_base->sysctl) & SOFTRESETALL) != 0x0) { 150eb9a28f6SNishanth Menon if (get_timer(0) - start > MAX_RETRY_MS) { 151eb9a28f6SNishanth Menon printf("%s: timedout waiting for softresetall!\n", 152eb9a28f6SNishanth Menon __func__); 153eb9a28f6SNishanth Menon return TIMEOUT; 154eb9a28f6SNishanth Menon } 155eb9a28f6SNishanth Menon } 156de941241SSukumar Ghorai writel(DTW_1_BITMODE | SDBP_PWROFF | SDVS_3V0, &mmc_base->hctl); 157de941241SSukumar Ghorai writel(readl(&mmc_base->capa) | VS30_3V0SUP | VS18_1V8SUP, 158de941241SSukumar Ghorai &mmc_base->capa); 159de941241SSukumar Ghorai 160de941241SSukumar Ghorai reg_val = readl(&mmc_base->con) & RESERVED_MASK; 161de941241SSukumar Ghorai 162de941241SSukumar Ghorai writel(CTPL_MMC_SD | reg_val | WPP_ACTIVEHIGH | CDP_ACTIVEHIGH | 163de941241SSukumar Ghorai MIT_CTO | DW8_1_4BITMODE | MODE_FUNC | STR_BLOCK | 164de941241SSukumar Ghorai HR_NOHOSTRESP | INIT_NOINIT | NOOPENDRAIN, &mmc_base->con); 165de941241SSukumar Ghorai 166de941241SSukumar Ghorai dsor = 240; 167de941241SSukumar Ghorai mmc_reg_out(&mmc_base->sysctl, (ICE_MASK | DTO_MASK | CEN_MASK), 168de941241SSukumar Ghorai (ICE_STOP | DTO_15THDTO | CEN_DISABLE)); 169de941241SSukumar Ghorai mmc_reg_out(&mmc_base->sysctl, ICE_MASK | CLKD_MASK, 170de941241SSukumar Ghorai (dsor << CLKD_OFFSET) | ICE_OSCILLATE); 171eb9a28f6SNishanth Menon start = get_timer(0); 172eb9a28f6SNishanth Menon while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) { 173eb9a28f6SNishanth Menon if (get_timer(0) - start > MAX_RETRY_MS) { 174eb9a28f6SNishanth Menon printf("%s: timedout waiting for ics!\n", __func__); 175eb9a28f6SNishanth Menon return TIMEOUT; 176eb9a28f6SNishanth Menon } 177eb9a28f6SNishanth Menon } 178de941241SSukumar Ghorai writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl); 179de941241SSukumar Ghorai 180de941241SSukumar Ghorai writel(readl(&mmc_base->hctl) | SDBP_PWRON, &mmc_base->hctl); 181de941241SSukumar Ghorai 182de941241SSukumar Ghorai writel(IE_BADA | IE_CERR | IE_DEB | IE_DCRC | IE_DTO | IE_CIE | 183de941241SSukumar Ghorai IE_CEB | IE_CCRC | IE_CTO | IE_BRR | IE_BWR | IE_TC | IE_CC, 184de941241SSukumar Ghorai &mmc_base->ie); 185de941241SSukumar Ghorai 186de941241SSukumar Ghorai mmc_init_stream(mmc_base); 187de941241SSukumar Ghorai 188de941241SSukumar Ghorai return 0; 189de941241SSukumar Ghorai } 190de941241SSukumar Ghorai 191de941241SSukumar Ghorai 192de941241SSukumar Ghorai static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, 193de941241SSukumar Ghorai struct mmc_data *data) 194de941241SSukumar Ghorai { 195de941241SSukumar Ghorai hsmmc_t *mmc_base = (hsmmc_t *)mmc->priv; 196de941241SSukumar Ghorai unsigned int flags, mmc_stat; 197eb9a28f6SNishanth Menon ulong start; 198de941241SSukumar Ghorai 199eb9a28f6SNishanth Menon start = get_timer(0); 200eb9a28f6SNishanth Menon while ((readl(&mmc_base->pstate) & DATI_MASK) == DATI_CMDDIS) { 201eb9a28f6SNishanth Menon if (get_timer(0) - start > MAX_RETRY_MS) { 202eb9a28f6SNishanth Menon printf("%s: timedout waiting for cmddis!\n", __func__); 203eb9a28f6SNishanth Menon return TIMEOUT; 204eb9a28f6SNishanth Menon } 205eb9a28f6SNishanth Menon } 206de941241SSukumar Ghorai writel(0xFFFFFFFF, &mmc_base->stat); 207eb9a28f6SNishanth Menon start = get_timer(0); 208eb9a28f6SNishanth Menon while (readl(&mmc_base->stat)) { 209eb9a28f6SNishanth Menon if (get_timer(0) - start > MAX_RETRY_MS) { 210eb9a28f6SNishanth Menon printf("%s: timedout waiting for stat!\n", __func__); 211eb9a28f6SNishanth Menon return TIMEOUT; 212eb9a28f6SNishanth Menon } 213eb9a28f6SNishanth Menon } 214de941241SSukumar Ghorai /* 215de941241SSukumar Ghorai * CMDREG 216de941241SSukumar Ghorai * CMDIDX[13:8] : Command index 217de941241SSukumar Ghorai * DATAPRNT[5] : Data Present Select 218de941241SSukumar Ghorai * ENCMDIDX[4] : Command Index Check Enable 219de941241SSukumar Ghorai * ENCMDCRC[3] : Command CRC Check Enable 220de941241SSukumar Ghorai * RSPTYP[1:0] 221de941241SSukumar Ghorai * 00 = No Response 222de941241SSukumar Ghorai * 01 = Length 136 223de941241SSukumar Ghorai * 10 = Length 48 224de941241SSukumar Ghorai * 11 = Length 48 Check busy after response 225de941241SSukumar Ghorai */ 226de941241SSukumar Ghorai /* Delay added before checking the status of frq change 227de941241SSukumar Ghorai * retry not supported by mmc.c(core file) 228de941241SSukumar Ghorai */ 229de941241SSukumar Ghorai if (cmd->cmdidx == SD_CMD_APP_SEND_SCR) 230de941241SSukumar Ghorai udelay(50000); /* wait 50 ms */ 231de941241SSukumar Ghorai 232de941241SSukumar Ghorai if (!(cmd->resp_type & MMC_RSP_PRESENT)) 233de941241SSukumar Ghorai flags = 0; 234de941241SSukumar Ghorai else if (cmd->resp_type & MMC_RSP_136) 235de941241SSukumar Ghorai flags = RSP_TYPE_LGHT136 | CICE_NOCHECK; 236de941241SSukumar Ghorai else if (cmd->resp_type & MMC_RSP_BUSY) 237de941241SSukumar Ghorai flags = RSP_TYPE_LGHT48B; 238de941241SSukumar Ghorai else 239de941241SSukumar Ghorai flags = RSP_TYPE_LGHT48; 240de941241SSukumar Ghorai 241de941241SSukumar Ghorai /* enable default flags */ 242de941241SSukumar Ghorai flags = flags | (CMD_TYPE_NORMAL | CICE_NOCHECK | CCCE_NOCHECK | 243de941241SSukumar Ghorai MSBS_SGLEBLK | ACEN_DISABLE | BCE_DISABLE | DE_DISABLE); 244de941241SSukumar Ghorai 245de941241SSukumar Ghorai if (cmd->resp_type & MMC_RSP_CRC) 246de941241SSukumar Ghorai flags |= CCCE_CHECK; 247de941241SSukumar Ghorai if (cmd->resp_type & MMC_RSP_OPCODE) 248de941241SSukumar Ghorai flags |= CICE_CHECK; 249de941241SSukumar Ghorai 250de941241SSukumar Ghorai if (data) { 251de941241SSukumar Ghorai if ((cmd->cmdidx == MMC_CMD_READ_MULTIPLE_BLOCK) || 252de941241SSukumar Ghorai (cmd->cmdidx == MMC_CMD_WRITE_MULTIPLE_BLOCK)) { 253de941241SSukumar Ghorai flags |= (MSBS_MULTIBLK | BCE_ENABLE); 254de941241SSukumar Ghorai data->blocksize = 512; 255de941241SSukumar Ghorai writel(data->blocksize | (data->blocks << 16), 256de941241SSukumar Ghorai &mmc_base->blk); 257de941241SSukumar Ghorai } else 258de941241SSukumar Ghorai writel(data->blocksize | NBLK_STPCNT, &mmc_base->blk); 259de941241SSukumar Ghorai 260de941241SSukumar Ghorai if (data->flags & MMC_DATA_READ) 261de941241SSukumar Ghorai flags |= (DP_DATA | DDIR_READ); 262de941241SSukumar Ghorai else 263de941241SSukumar Ghorai flags |= (DP_DATA | DDIR_WRITE); 264de941241SSukumar Ghorai } 265de941241SSukumar Ghorai 266de941241SSukumar Ghorai writel(cmd->cmdarg, &mmc_base->arg); 267de941241SSukumar Ghorai writel((cmd->cmdidx << 24) | flags, &mmc_base->cmd); 268de941241SSukumar Ghorai 269eb9a28f6SNishanth Menon start = get_timer(0); 270de941241SSukumar Ghorai do { 271de941241SSukumar Ghorai mmc_stat = readl(&mmc_base->stat); 272eb9a28f6SNishanth Menon if (get_timer(0) - start > MAX_RETRY_MS) { 273de941241SSukumar Ghorai printf("%s : timeout: No status update\n", __func__); 274de941241SSukumar Ghorai return TIMEOUT; 275de941241SSukumar Ghorai } 276eb9a28f6SNishanth Menon } while (!mmc_stat); 277de941241SSukumar Ghorai 278de941241SSukumar Ghorai if ((mmc_stat & IE_CTO) != 0) 279de941241SSukumar Ghorai return TIMEOUT; 280de941241SSukumar Ghorai else if ((mmc_stat & ERRI_MASK) != 0) 281de941241SSukumar Ghorai return -1; 282de941241SSukumar Ghorai 283de941241SSukumar Ghorai if (mmc_stat & CC_MASK) { 284de941241SSukumar Ghorai writel(CC_MASK, &mmc_base->stat); 285de941241SSukumar Ghorai if (cmd->resp_type & MMC_RSP_PRESENT) { 286de941241SSukumar Ghorai if (cmd->resp_type & MMC_RSP_136) { 287de941241SSukumar Ghorai /* response type 2 */ 288de941241SSukumar Ghorai cmd->response[3] = readl(&mmc_base->rsp10); 289de941241SSukumar Ghorai cmd->response[2] = readl(&mmc_base->rsp32); 290de941241SSukumar Ghorai cmd->response[1] = readl(&mmc_base->rsp54); 291de941241SSukumar Ghorai cmd->response[0] = readl(&mmc_base->rsp76); 292de941241SSukumar Ghorai } else 293de941241SSukumar Ghorai /* response types 1, 1b, 3, 4, 5, 6 */ 294de941241SSukumar Ghorai cmd->response[0] = readl(&mmc_base->rsp10); 295de941241SSukumar Ghorai } 296de941241SSukumar Ghorai } 297de941241SSukumar Ghorai 298de941241SSukumar Ghorai if (data && (data->flags & MMC_DATA_READ)) { 299de941241SSukumar Ghorai mmc_read_data(mmc_base, data->dest, 300de941241SSukumar Ghorai data->blocksize * data->blocks); 301de941241SSukumar Ghorai } else if (data && (data->flags & MMC_DATA_WRITE)) { 302de941241SSukumar Ghorai mmc_write_data(mmc_base, data->src, 303de941241SSukumar Ghorai data->blocksize * data->blocks); 304de941241SSukumar Ghorai } 305de941241SSukumar Ghorai return 0; 306de941241SSukumar Ghorai } 307de941241SSukumar Ghorai 308de941241SSukumar Ghorai static int mmc_read_data(hsmmc_t *mmc_base, char *buf, unsigned int size) 309de941241SSukumar Ghorai { 310de941241SSukumar Ghorai unsigned int *output_buf = (unsigned int *)buf; 311de941241SSukumar Ghorai unsigned int mmc_stat; 312de941241SSukumar Ghorai unsigned int count; 313de941241SSukumar Ghorai 314de941241SSukumar Ghorai /* 315de941241SSukumar Ghorai * Start Polled Read 316de941241SSukumar Ghorai */ 317de941241SSukumar Ghorai count = (size > MMCSD_SECTOR_SIZE) ? MMCSD_SECTOR_SIZE : size; 318de941241SSukumar Ghorai count /= 4; 319de941241SSukumar Ghorai 320de941241SSukumar Ghorai while (size) { 321eb9a28f6SNishanth Menon ulong start = get_timer(0); 322de941241SSukumar Ghorai do { 323de941241SSukumar Ghorai mmc_stat = readl(&mmc_base->stat); 324eb9a28f6SNishanth Menon if (get_timer(0) - start > MAX_RETRY_MS) { 325eb9a28f6SNishanth Menon printf("%s: timedout waiting for status!\n", 326eb9a28f6SNishanth Menon __func__); 327eb9a28f6SNishanth Menon return TIMEOUT; 328eb9a28f6SNishanth Menon } 329de941241SSukumar Ghorai } while (mmc_stat == 0); 330de941241SSukumar Ghorai 331de941241SSukumar Ghorai if ((mmc_stat & ERRI_MASK) != 0) 332de941241SSukumar Ghorai return 1; 333de941241SSukumar Ghorai 334de941241SSukumar Ghorai if (mmc_stat & BRR_MASK) { 335de941241SSukumar Ghorai unsigned int k; 336de941241SSukumar Ghorai 337de941241SSukumar Ghorai writel(readl(&mmc_base->stat) | BRR_MASK, 338de941241SSukumar Ghorai &mmc_base->stat); 339de941241SSukumar Ghorai for (k = 0; k < count; k++) { 340de941241SSukumar Ghorai *output_buf = readl(&mmc_base->data); 341de941241SSukumar Ghorai output_buf++; 342de941241SSukumar Ghorai } 343de941241SSukumar Ghorai size -= (count*4); 344de941241SSukumar Ghorai } 345de941241SSukumar Ghorai 346de941241SSukumar Ghorai if (mmc_stat & BWR_MASK) 347de941241SSukumar Ghorai writel(readl(&mmc_base->stat) | BWR_MASK, 348de941241SSukumar Ghorai &mmc_base->stat); 349de941241SSukumar Ghorai 350de941241SSukumar Ghorai if (mmc_stat & TC_MASK) { 351de941241SSukumar Ghorai writel(readl(&mmc_base->stat) | TC_MASK, 352de941241SSukumar Ghorai &mmc_base->stat); 353de941241SSukumar Ghorai break; 354de941241SSukumar Ghorai } 355de941241SSukumar Ghorai } 356de941241SSukumar Ghorai return 0; 357de941241SSukumar Ghorai } 358de941241SSukumar Ghorai 359de941241SSukumar Ghorai static int mmc_write_data(hsmmc_t *mmc_base, const char *buf, unsigned int size) 360de941241SSukumar Ghorai { 361de941241SSukumar Ghorai unsigned int *input_buf = (unsigned int *)buf; 362de941241SSukumar Ghorai unsigned int mmc_stat; 363de941241SSukumar Ghorai unsigned int count; 364de941241SSukumar Ghorai 365de941241SSukumar Ghorai /* 366de941241SSukumar Ghorai * Start Polled Read 367de941241SSukumar Ghorai */ 368de941241SSukumar Ghorai count = (size > MMCSD_SECTOR_SIZE) ? MMCSD_SECTOR_SIZE : size; 369de941241SSukumar Ghorai count /= 4; 370de941241SSukumar Ghorai 371de941241SSukumar Ghorai while (size) { 372eb9a28f6SNishanth Menon ulong start = get_timer(0); 373de941241SSukumar Ghorai do { 374de941241SSukumar Ghorai mmc_stat = readl(&mmc_base->stat); 375eb9a28f6SNishanth Menon if (get_timer(0) - start > MAX_RETRY_MS) { 376eb9a28f6SNishanth Menon printf("%s: timedout waiting for status!\n", 377eb9a28f6SNishanth Menon __func__); 378eb9a28f6SNishanth Menon return TIMEOUT; 379eb9a28f6SNishanth Menon } 380de941241SSukumar Ghorai } while (mmc_stat == 0); 381de941241SSukumar Ghorai 382de941241SSukumar Ghorai if ((mmc_stat & ERRI_MASK) != 0) 383de941241SSukumar Ghorai return 1; 384de941241SSukumar Ghorai 385de941241SSukumar Ghorai if (mmc_stat & BWR_MASK) { 386de941241SSukumar Ghorai unsigned int k; 387de941241SSukumar Ghorai 388de941241SSukumar Ghorai writel(readl(&mmc_base->stat) | BWR_MASK, 389de941241SSukumar Ghorai &mmc_base->stat); 390de941241SSukumar Ghorai for (k = 0; k < count; k++) { 391de941241SSukumar Ghorai writel(*input_buf, &mmc_base->data); 392de941241SSukumar Ghorai input_buf++; 393de941241SSukumar Ghorai } 394de941241SSukumar Ghorai size -= (count*4); 395de941241SSukumar Ghorai } 396de941241SSukumar Ghorai 397de941241SSukumar Ghorai if (mmc_stat & BRR_MASK) 398de941241SSukumar Ghorai writel(readl(&mmc_base->stat) | BRR_MASK, 399de941241SSukumar Ghorai &mmc_base->stat); 400de941241SSukumar Ghorai 401de941241SSukumar Ghorai if (mmc_stat & TC_MASK) { 402de941241SSukumar Ghorai writel(readl(&mmc_base->stat) | TC_MASK, 403de941241SSukumar Ghorai &mmc_base->stat); 404de941241SSukumar Ghorai break; 405de941241SSukumar Ghorai } 406de941241SSukumar Ghorai } 407de941241SSukumar Ghorai return 0; 408de941241SSukumar Ghorai } 409de941241SSukumar Ghorai 410de941241SSukumar Ghorai static void mmc_set_ios(struct mmc *mmc) 411de941241SSukumar Ghorai { 412de941241SSukumar Ghorai hsmmc_t *mmc_base = (hsmmc_t *)mmc->priv; 413de941241SSukumar Ghorai unsigned int dsor = 0; 414eb9a28f6SNishanth Menon ulong start; 415de941241SSukumar Ghorai 416de941241SSukumar Ghorai /* configue bus width */ 417de941241SSukumar Ghorai switch (mmc->bus_width) { 418de941241SSukumar Ghorai case 8: 419de941241SSukumar Ghorai writel(readl(&mmc_base->con) | DTW_8_BITMODE, 420de941241SSukumar Ghorai &mmc_base->con); 421de941241SSukumar Ghorai break; 422de941241SSukumar Ghorai 423de941241SSukumar Ghorai case 4: 424de941241SSukumar Ghorai writel(readl(&mmc_base->con) & ~DTW_8_BITMODE, 425de941241SSukumar Ghorai &mmc_base->con); 426de941241SSukumar Ghorai writel(readl(&mmc_base->hctl) | DTW_4_BITMODE, 427de941241SSukumar Ghorai &mmc_base->hctl); 428de941241SSukumar Ghorai break; 429de941241SSukumar Ghorai 430de941241SSukumar Ghorai case 1: 431de941241SSukumar Ghorai default: 432de941241SSukumar Ghorai writel(readl(&mmc_base->con) & ~DTW_8_BITMODE, 433de941241SSukumar Ghorai &mmc_base->con); 434de941241SSukumar Ghorai writel(readl(&mmc_base->hctl) & ~DTW_4_BITMODE, 435de941241SSukumar Ghorai &mmc_base->hctl); 436de941241SSukumar Ghorai break; 437de941241SSukumar Ghorai } 438de941241SSukumar Ghorai 439de941241SSukumar Ghorai /* configure clock with 96Mhz system clock. 440de941241SSukumar Ghorai */ 441de941241SSukumar Ghorai if (mmc->clock != 0) { 442de941241SSukumar Ghorai dsor = (MMC_CLOCK_REFERENCE * 1000000 / mmc->clock); 443de941241SSukumar Ghorai if ((MMC_CLOCK_REFERENCE * 1000000) / dsor > mmc->clock) 444de941241SSukumar Ghorai dsor++; 445de941241SSukumar Ghorai } 446de941241SSukumar Ghorai 447de941241SSukumar Ghorai mmc_reg_out(&mmc_base->sysctl, (ICE_MASK | DTO_MASK | CEN_MASK), 448de941241SSukumar Ghorai (ICE_STOP | DTO_15THDTO | CEN_DISABLE)); 449de941241SSukumar Ghorai 450de941241SSukumar Ghorai mmc_reg_out(&mmc_base->sysctl, ICE_MASK | CLKD_MASK, 451de941241SSukumar Ghorai (dsor << CLKD_OFFSET) | ICE_OSCILLATE); 452de941241SSukumar Ghorai 453eb9a28f6SNishanth Menon start = get_timer(0); 454eb9a28f6SNishanth Menon while ((readl(&mmc_base->sysctl) & ICS_MASK) == ICS_NOTREADY) { 455eb9a28f6SNishanth Menon if (get_timer(0) - start > MAX_RETRY_MS) { 456eb9a28f6SNishanth Menon printf("%s: timedout waiting for ics!\n", __func__); 457eb9a28f6SNishanth Menon return; 458eb9a28f6SNishanth Menon } 459eb9a28f6SNishanth Menon } 460de941241SSukumar Ghorai writel(readl(&mmc_base->sysctl) | CEN_ENABLE, &mmc_base->sysctl); 461de941241SSukumar Ghorai } 462de941241SSukumar Ghorai 463de941241SSukumar Ghorai int omap_mmc_init(int dev_index) 464de941241SSukumar Ghorai { 465de941241SSukumar Ghorai struct mmc *mmc; 466de941241SSukumar Ghorai 467de941241SSukumar Ghorai mmc = &hsmmc_dev[dev_index]; 468de941241SSukumar Ghorai 469de941241SSukumar Ghorai sprintf(mmc->name, "OMAP SD/MMC"); 470de941241SSukumar Ghorai mmc->send_cmd = mmc_send_cmd; 471de941241SSukumar Ghorai mmc->set_ios = mmc_set_ios; 472de941241SSukumar Ghorai mmc->init = mmc_init_setup; 473de941241SSukumar Ghorai 474de941241SSukumar Ghorai switch (dev_index) { 475de941241SSukumar Ghorai case 0: 476de941241SSukumar Ghorai mmc->priv = (hsmmc_t *)OMAP_HSMMC1_BASE; 477de941241SSukumar Ghorai break; 478*1037d585STom Rini #ifdef OMAP_HSMMC2_BASE 479de941241SSukumar Ghorai case 1: 480de941241SSukumar Ghorai mmc->priv = (hsmmc_t *)OMAP_HSMMC2_BASE; 481de941241SSukumar Ghorai break; 482*1037d585STom Rini #endif 483*1037d585STom Rini #ifdef OMAP_HSMMC3_BASE 484de941241SSukumar Ghorai case 2: 485de941241SSukumar Ghorai mmc->priv = (hsmmc_t *)OMAP_HSMMC3_BASE; 486de941241SSukumar Ghorai break; 487*1037d585STom Rini #endif 488de941241SSukumar Ghorai default: 489de941241SSukumar Ghorai mmc->priv = (hsmmc_t *)OMAP_HSMMC1_BASE; 490de941241SSukumar Ghorai return 1; 491de941241SSukumar Ghorai } 492de941241SSukumar Ghorai mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; 493ecd9af88SBalaji T K mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_HS_52MHz | MMC_MODE_HS | 494ecd9af88SBalaji T K MMC_MODE_HC; 495de941241SSukumar Ghorai 496de941241SSukumar Ghorai mmc->f_min = 400000; 497de941241SSukumar Ghorai mmc->f_max = 52000000; 498de941241SSukumar Ghorai 4998feafcc4SJohn Rigby mmc->b_max = 0; 5008feafcc4SJohn Rigby 5014ca9244dSJohn Rigby #if defined(CONFIG_OMAP34XX) 5024ca9244dSJohn Rigby /* 5034ca9244dSJohn Rigby * Silicon revs 2.1 and older do not support multiblock transfers. 5044ca9244dSJohn Rigby */ 5054ca9244dSJohn Rigby if ((get_cpu_family() == CPU_OMAP34XX) && (get_cpu_rev() <= CPU_3XX_ES21)) 5064ca9244dSJohn Rigby mmc->b_max = 1; 5074ca9244dSJohn Rigby #endif 5084ca9244dSJohn Rigby 509de941241SSukumar Ghorai mmc_register(mmc); 510de941241SSukumar Ghorai 511de941241SSukumar Ghorai return 0; 512de941241SSukumar Ghorai } 513