/** * Read one or several block(s) of data from the card * @param mci MCI instance * @param dst Where to store the data read from the card * @param blocknum Block number to read * @param blocks number of blocks to read */ static int mci_read_block(struct mci *mci, void *dst, int blocknum, int blocks) { struct mci_cmd cmd; struct mci_data data; int ret; unsigned mmccmd; if (blocks > 1) mmccmd = MMC_CMD_READ_MULTIPLE_BLOCK; else mmccmd = MMC_CMD_READ_SINGLE_BLOCK; mci_setup_cmd(&cmd, mmccmd, mci->high_capacity != 0 ? blocknum : blocknum * mci->read_bl_len, MMC_RSP_R1); data.dest = dst; data.blocks = blocks; data.blocksize = mci->read_bl_len; data.flags = MMC_DATA_READ; ret = mci_send_cmd(mci, &cmd, &data); if (ret || blocks > 1) { mci_setup_cmd(&cmd, MMC_CMD_STOP_TRANSMISSION, 0, MMC_RSP_R1b); mci_send_cmd(mci, &cmd, NULL); } return ret; }
static void rk_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct rk_mmc *host = mmc_priv(mmc); u32 regs, div; /* set default 1 bit mode */ host->ctype = MMC_CTYPE_1BIT; switch (ios->bus_width) { case MMC_BUS_WIDTH_1: host->ctype = MMC_CTYPE_1BIT; break; case MMC_BUS_WIDTH_4: host->ctype = MMC_CTYPE_4BIT; break; case MMC_BUS_WIDTH_8: host->ctype = MMC_CTYPE_8BIT; break; } /* DDR mode set */ if (ios->timing == MMC_TIMING_UHS_DDR50){ regs = mmc_readl(host, UHS_REG); regs |= MMC_UHS_DDR_MODE; mmc_writel(host, UHS_REG, regs); } if (ios->clock && ios->clock != host->curr_clock) { if (host->bus_hz % ios->clock) div = ((host->bus_hz / ios->clock) >> 1) + 1; else div = (host->bus_hz / ios->clock) >> 1; mmc_dbg(host, "Bus clock: %dHz, req: %dHz, actual: %dHz, div: %d\n", host->bus_hz, ios->clock, div ? ((host->bus_hz / div) >> 1) : host->bus_hz, div); /* disable clock */ mmc_writel(host, CLKENA, 0); mmc_writel(host, CLKSRC, 0); /* inform CIU */ mci_send_cmd(host, MMC_CMD_UPD_CLK | MMC_CMD_PRV_DAT_WAIT, 0); /* set clock to desired speed */ mmc_writel(host, CLKDIV, div); /* inform CIU */ mci_send_cmd(host, MMC_CMD_UPD_CLK | MMC_CMD_PRV_DAT_WAIT, 0); /* enable clock */ mmc_writel(host, CLKENA, MMC_CLKEN_ENABLE | MMC_CLKEN_LOW_PWR); /* inform CIU */ mci_send_cmd(host, MMC_CMD_UPD_CLK | MMC_CMD_PRV_DAT_WAIT, 0); host->curr_clock = ios->clock; }
/** * Setup SD/MMC card's blocklength to be used for future transmitts * @param mci_dev MCI instance * @param len Blocklength in bytes * @return Transaction status (0 on success) */ static int mci_set_blocklen(struct mci *mci, unsigned len) { struct mci_cmd cmd; mci_setup_cmd(&cmd, MMC_CMD_SET_BLOCKLEN, len, MMC_RSP_R1); return mci_send_cmd(mci, &cmd, NULL); }
/** * configure optional DSR value * @param mci_dev MCI instance * @return Transaction status (0 on success) */ static int mci_set_dsr(struct mci *mci) { struct mci_cmd cmd; mci_setup_cmd(&cmd, MMC_CMD_SET_DSR, (mci->host->dsr_val >> 16) | 0xffff, MMC_RSP_NONE); return mci_send_cmd(mci, &cmd, NULL); }
/** * Write one or several blocks of data to the card * @param mci_dev MCI instance * @param src Where to read from to write to the card * @param blocknum Block number to write * @param blocks Block count to write * @return Transaction status (0 on success) */ static int mci_block_write(struct mci *mci, const void *src, int blocknum, int blocks) { struct mci_cmd cmd; struct mci_data data; const void *buf; unsigned mmccmd; int ret; if (blocks > 1) mmccmd = MMC_CMD_WRITE_MULTIPLE_BLOCK; else mmccmd = MMC_CMD_WRITE_SINGLE_BLOCK; if ((unsigned long)src & 0x3) { memcpy(sector_buf, src, 512); buf = sector_buf; } else { buf = src; } mci_setup_cmd(&cmd, mmccmd, mci->high_capacity != 0 ? blocknum : blocknum * mci->write_bl_len, MMC_RSP_R1); data.src = buf; data.blocks = blocks; data.blocksize = mci->write_bl_len; data.flags = MMC_DATA_WRITE; ret = mci_send_cmd(mci, &cmd, &data); if (ret || blocks > 1) { mci_setup_cmd(&cmd, MMC_CMD_STOP_TRANSMISSION, 0, MMC_RSP_R1b); mci_send_cmd(mci, &cmd, NULL); } return ret; }
/** * FIXME * @param mci MCI instance * @param set FIXME * @param index FIXME * @param value FIXME * @return Transaction status (0 on success) */ static int mci_switch(struct mci *mci, unsigned set, unsigned index, unsigned value) { struct mci_cmd cmd; mci_setup_cmd(&cmd, MMC_CMD_SWITCH, (MMC_SWITCH_MODE_WRITE_BYTE << 24) | (index << 16) | (value << 8), MMC_RSP_R1b); return mci_send_cmd(mci, &cmd, NULL); }
/** * FIXME * @param mci MCI instance * @param ext_csd Buffer for a 512 byte sized extended CSD * @return Transaction status (0 on success) * * Note: Only cards newer than Version 1.1 (Physical Layer Spec) support * this command */ static int mci_send_ext_csd(struct mci *mci, char *ext_csd) { struct mci_cmd cmd; struct mci_data data; /* Get the Card Status Register */ mci_setup_cmd(&cmd, MMC_CMD_SEND_EXT_CSD, 0, MMC_RSP_R1); data.dest = ext_csd; data.blocks = 1; data.blocksize = 512; data.flags = MMC_DATA_READ; return mci_send_cmd(mci, &cmd, &data); }
/** * Reset the attached MMC/SD card * @param mci MCI instance * @return Transaction status (0 on success) */ static int mci_go_idle(struct mci *mci) { struct mci_cmd cmd; int err; udelay(1000); mci_setup_cmd(&cmd, MMC_CMD_GO_IDLE_STATE, 0, MMC_RSP_NONE); err = mci_send_cmd(mci, &cmd, NULL); if (err) { dev_dbg(mci->mci_dev, "Activating IDLE state failed: %d\n", err); return err; } udelay(2000); /* WTF? */ return 0; }
/** * FIXME * @param mci MCI instance * @param mode FIXME * @param group FIXME * @param value FIXME * @param resp FIXME * @return Transaction status (0 on success) */ static int sd_switch(struct mci *mci, unsigned mode, unsigned group, unsigned value, uint8_t *resp) { struct mci_cmd cmd; struct mci_data data; unsigned arg; arg = (mode << 31) | 0xffffff; arg &= ~(0xf << (group << 2)); arg |= value << (group << 2); /* Switch the frequency */ mci_setup_cmd(&cmd, SD_CMD_SWITCH_FUNC, arg, MMC_RSP_R1); data.dest = resp; data.blocksize = 64; data.blocks = 1; data.flags = MMC_DATA_READ; return mci_send_cmd(mci, &cmd, &data); }
/** * Setup the operation conditions to a MultiMediaCard * @param mci MCI instance * @return Transaction status (0 on success) */ static int mmc_send_op_cond(struct mci *mci) { struct mci_host *host = mci->host; struct mci_cmd cmd; int timeout = 1000; int err; /* Some cards seem to need this */ mci_go_idle(mci); do { mci_setup_cmd(&cmd, MMC_CMD_SEND_OP_COND, OCR_HCS | host->voltages, MMC_RSP_R3); err = mci_send_cmd(mci, &cmd, NULL); if (err) { dev_dbg(mci->mci_dev, "Preparing MMC for operating conditions failed: %d\n", err); return err; } udelay(1000); } while (!(cmd.response[0] & OCR_BUSY) && timeout--); if (timeout <= 0) { dev_dbg(mci->mci_dev, "SD operation condition set timed out\n"); return -ENODEV; } mci->version = MMC_VERSION_UNKNOWN; mci->ocr = cmd.response[0]; mci->high_capacity = ((mci->ocr & OCR_HCS) == OCR_HCS); mci->rca = 0; return 0; }
/** * Change transfer frequency for an SD card * @param mci MCI instance * @return Transaction status (0 on success) */ static int sd_change_freq(struct mci *mci) { struct mci_cmd cmd; struct mci_data data; #ifdef CONFIG_MCI_SPI struct mci_host *host = mci->host; #endif uint32_t *switch_status = sector_buf; uint32_t *scr = sector_buf; int timeout; int err; if (mmc_host_is_spi(host)) return 0; dev_dbg(mci->mci_dev, "Changing transfer frequency\n"); mci->card_caps = 0; /* Read the SCR to find out if this card supports higher speeds */ mci_setup_cmd(&cmd, MMC_CMD_APP_CMD, mci->rca << 16, MMC_RSP_R1); err = mci_send_cmd(mci, &cmd, NULL); if (err) { dev_dbg(mci->mci_dev, "Query SD card capabilities failed: %d\n", err); return err; } mci_setup_cmd(&cmd, SD_CMD_APP_SEND_SCR, 0, MMC_RSP_R1); timeout = 3; retry_scr: dev_dbg(mci->mci_dev, "Trying to read the SCR (try %d of %d)\n", 4 - timeout, 3); data.dest = (char *)scr; data.blocksize = 8; data.blocks = 1; data.flags = MMC_DATA_READ; err = mci_send_cmd(mci, &cmd, &data); if (err) { dev_dbg(mci->mci_dev, " Catch error (%d)", err); if (timeout--) { dev_dbg(mci->mci_dev, "-- retrying\n"); goto retry_scr; } dev_dbg(mci->mci_dev, "-- giving up\n"); return err; } mci->scr[0] = __be32_to_cpu(scr[0]); mci->scr[1] = __be32_to_cpu(scr[1]); switch ((mci->scr[0] >> 24) & 0xf) { case 0: mci->version = SD_VERSION_1_0; break; case 1: mci->version = SD_VERSION_1_10; break; case 2: mci->version = SD_VERSION_2; break; default: mci->version = SD_VERSION_1_0; break; } /* Version 1.0 doesn't support switching */ if (mci->version == SD_VERSION_1_0) return 0; timeout = 4; while (timeout--) { err = sd_switch(mci, SD_SWITCH_CHECK, 0, 1, (uint8_t*)switch_status); if (err) { dev_dbg(mci->mci_dev, "Checking SD transfer switch frequency feature failed: %d\n", err); return err; } /* The high-speed function is busy. Try again */ if (!(__be32_to_cpu(switch_status[7]) & SD_HIGHSPEED_BUSY)) break; } if (mci->scr[0] & SD_DATA_4BIT) mci->card_caps |= MMC_MODE_4BIT; /* If high-speed isn't supported, we return */ if (!(__be32_to_cpu(switch_status[3]) & SD_HIGHSPEED_SUPPORTED)) return 0; err = sd_switch(mci, SD_SWITCH_SWITCH, 0, 1, (uint8_t*)switch_status); if (err) { dev_dbg(mci->mci_dev, "Switching SD transfer frequency failed: %d\n", err); return err; } if ((__be32_to_cpu(switch_status[4]) & 0x0f000000) == 0x01000000) mci->card_caps |= MMC_MODE_HS; return 0; }
/** * FIXME * @param mci MCI instance * @return Transaction status (0 on success) */ static int sd_send_op_cond(struct mci *mci) { struct mci_host *host = mci->host; struct mci_cmd cmd; int timeout = 1000; int err; unsigned voltages; unsigned busy; unsigned arg; /* * Most cards do not answer if some reserved bits * in the ocr are set. However, Some controller * can set bit 7 (reserved for low voltages), but * how to manage low voltages SD card is not yet * specified. */ voltages = host->voltages & 0xff8000; do { mci_setup_cmd(&cmd, MMC_CMD_APP_CMD, 0, MMC_RSP_R1); err = mci_send_cmd(mci, &cmd, NULL); if (err) { dev_dbg(mci->mci_dev, "Preparing SD for operating conditions failed: %d\n", err); return err; } arg = mmc_host_is_spi(host) ? 0 : voltages; if (mci->version == SD_VERSION_2) arg |= OCR_HCS; mci_setup_cmd(&cmd, SD_CMD_APP_SEND_OP_COND, arg, MMC_RSP_R3); err = mci_send_cmd(mci, &cmd, NULL); if (err) { dev_dbg(mci->mci_dev, "SD operation condition set failed: %d\n", err); return err; } udelay(1000); if (mmc_host_is_spi(host)) busy = cmd.response[0] & R1_SPI_IDLE; else busy = !(cmd.response[0] & OCR_BUSY); } while (busy && timeout--); if (timeout <= 0) { dev_dbg(mci->mci_dev, "SD operation condition set timed out\n"); return -ENODEV; } if (mci->version != SD_VERSION_2) mci->version = SD_VERSION_1_0; if (mmc_host_is_spi(host)) { /* read OCR for spi */ mci_setup_cmd(&cmd, MMC_CMD_SPI_READ_OCR, 0, MMC_RSP_R3); err = mci_send_cmd(mci, &cmd, NULL); if (err) return err; } mci->ocr = cmd.response[0]; mci->high_capacity = ((mci->ocr & OCR_HCS) == OCR_HCS); mci->rca = 0; return 0; }