diff options
Diffstat (limited to 'drivers/mci/mci-core.c')
-rw-r--r-- | drivers/mci/mci-core.c | 958 |
1 files changed, 805 insertions, 153 deletions
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index 34aaee54f9..a3b25ea01a 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -1,26 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// SPDX-FileCopyrightText: 2010 Juergen Beisert, Pengutronix +// SPDX-FileCopyrightText: 2008 Freescale Semiconductor, Inc + /* - * (C) Copyright 2010 Juergen Beisert, Pengutronix - * - * This code is havily inspired and in parts from the u-boot project: - * - * Copyright 2008, Freescale Semiconductor, Inc - * Andy Fleming - * - * Based vaguely on the Linux code - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * + * This code is heavily inspired and in parts from the u-boot project which is + * based vaguely on the Linux code */ /* #define DEBUG */ @@ -30,12 +14,14 @@ #include <mci.h> #include <malloc.h> #include <errno.h> -#include <asm-generic/div64.h> +#include <linux/math64.h> #include <asm/byteorder.h> #include <block.h> #include <disks.h> #include <of.h> #include <linux/err.h> +#include <linux/sizes.h> +#include <dma.h> #define MAX_BUFFER_NUMBER 0xffffffff @@ -89,6 +75,28 @@ static int mci_send_cmd(struct mci *mci, struct mci_cmd *cmd, struct mci_data *d } /** + * mci_send_cmd_retry() - send a command to the mmc device, retrying on error + * + * @dev: device to receive the command + * @cmd: command to send + * @data: additional data to send/receive + * @retries: how many times to retry; mci_send_cmd is always called at least + * once + * Return: 0 if ok, -ve on error + */ +static int mci_send_cmd_retry(struct mci *mci, struct mci_cmd *cmd, + struct mci_data *data, unsigned retries) +{ + int ret; + + do + ret = mci_send_cmd(mci, cmd, data); + while (ret && retries--); + + return ret; +} + +/** * @param p Command definition to setup * @param cmd Valid SD/MMC command (refer MMC_CMD_* / SD_CMD_*) * @param arg Argument for the command (optional) @@ -127,12 +135,105 @@ static int mci_set_blocklen(struct mci *mci, unsigned len) { struct mci_cmd cmd; + if (mci->host->timing == MMC_TIMING_MMC_DDR52) + return 0; + mci_setup_cmd(&cmd, MMC_CMD_SET_BLOCKLEN, len, MMC_RSP_R1); return mci_send_cmd(mci, &cmd, NULL); } static void *sector_buf; +static int mci_send_status(struct mci *mci, unsigned int *status) +{ + struct mci_host *host = mci->host; + struct mci_cmd cmd; + int ret; + + /* + * While CMD13 is defined for SPI mode, the reported status bits have + * different layout that SD/MMC. We skip supporting this for now. + */ + if (mmc_host_is_spi(host)) + return -ENOSYS; + + cmd.cmdidx = MMC_CMD_SEND_STATUS; + cmd.resp_type = MMC_RSP_R1; + cmd.cmdarg = mci->rca << 16; + + ret = mci_send_cmd_retry(mci, &cmd, NULL, 4); + if (!ret) + *status = cmd.response[0]; + + return ret; +} + +static int mmc_switch_status_error(struct mci_host *host, u32 status) +{ + if (mmc_host_is_spi(host)) { + if (status & R1_SPI_ILLEGAL_COMMAND) + return -EBADMSG; + } else { + if (R1_STATUS(status)) + pr_warn("unexpected status %#x after switch\n", status); + if (status & R1_SWITCH_ERROR) + return -EBADMSG; + } + return 0; +} + +/* Caller must hold re-tuning */ +int mci_switch_status(struct mci *mci, bool crc_err_fatal) +{ + u32 status; + int err; + + err = mci_send_status(mci, &status); + if (!crc_err_fatal && err == -EILSEQ) + return 0; + if (err) + return err; + + return mmc_switch_status_error(mci->host, status); +} + +static int mci_poll_until_ready(struct mci *mci, int timeout_ms) +{ + unsigned int status; + int err, retries = 0; + + while (1) { + err = mci_send_status(mci, &status); + if (err) + return err; + + /* + * Some cards mishandle the status bits, so make sure to + * check both the busy indication and the card state. + */ + if ((status & R1_READY_FOR_DATA) && + R1_CURRENT_STATE(status) != R1_STATE_PRG) + break; + + if (status & R1_STATUS_MASK) { + dev_err(&mci->dev, "Status Error: 0x%08x\n", status); + return -EIO; + } + + if (retries++ == timeout_ms) { + dev_err(&mci->dev, "Timeout awaiting card ready\n"); + return -ETIMEDOUT; + } + + udelay(1000); + } + + dev_dbg(&mci->dev, "Ready polling took %ums\n", retries); + + return 0; +} + + /** * Write one or several blocks of data to the card * @param mci_dev MCI instance @@ -146,28 +247,31 @@ static int mci_block_write(struct mci *mci, const void *src, int blocknum, { struct mci_cmd cmd; struct mci_data data; - const void *buf; unsigned mmccmd; int ret; + /* + * Quoting eMMC Spec v5.1 (JEDEC Standard No. 84-B51): + * Due to legacy reasons, a Device may still treat CMD24/25 during + * prg-state (while busy is active) as a legal or illegal command. + * A host should not send CMD24/25 while the Device is in the prg + * state and busy is active. + */ + ret = mci_poll_until_ready(mci, 1000 /* ms */); + if (ret && ret != -ENOSYS) + return 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.src = src; data.blocks = blocks; data.blocksize = mci->write_bl_len; data.flags = MMC_DATA_WRITE; @@ -215,7 +319,8 @@ static int mci_read_block(struct mci *mci, void *dst, int blocknum, ret = mci_send_cmd(mci, &cmd, &data); if (ret || blocks > 1) { - mci_setup_cmd(&cmd, MMC_CMD_STOP_TRANSMISSION, 0, MMC_RSP_R1b); + mci_setup_cmd(&cmd, MMC_CMD_STOP_TRANSMISSION, 0, + IS_SD(mci) ? MMC_RSP_R1b : MMC_RSP_R1); mci_send_cmd(mci, &cmd, NULL); } return ret; @@ -246,6 +351,15 @@ static int mci_go_idle(struct mci *mci) return 0; } +static int sdio_send_op_cond(struct mci *mci) +{ + struct mci_cmd cmd; + + mci_setup_cmd(&cmd, SD_IO_SEND_OP_COND, 0, MMC_RSP_SPI_R4 | MMC_RSP_R4 | MMC_CMD_BCR); + + return mci_send_cmd(mci, &cmd, NULL); +} + /** * FIXME * @param mci MCI instance @@ -358,15 +472,15 @@ static int mmc_send_op_cond(struct mci *mci) mci->ocr = cmd.response[0]; mci->high_capacity = ((mci->ocr & OCR_HCS) == OCR_HCS); - mci->rca = 0; + mci->rca = 2; return 0; } /** - * FIXME - * @param mci MCI instance - * @param ext_csd Buffer for a 512 byte sized extended CSD + * Read-in the card's whole extended CSD configuration area + * @param[in] mci MCI instance + * @param[out] ext_csd Buffer for an #EXT_CSD_BLOCKSIZE byte sized extended CSD * @return Transaction status (0 on success) * * Note: Only cards newer than Version 1.1 (Physical Layer Spec) support @@ -389,16 +503,22 @@ int mci_send_ext_csd(struct mci *mci, char *ext_csd) } /** - * FIXME - * @param mci MCI instance - * @param set FIXME - * @param index FIXME - * @param value FIXME + * Write a byte into the card's extended CSD configuration area + * @param[in] mci MCI instance + * @param[in] index Byte index in the extended CSD configuration area + * @param[in] value Byte to write at index into the extended CSD configuration area * @return Transaction status (0 on success) + * + * This sends a CMD6 (aka SWITCH) to the card and writes @b value at extended CSD @b index. + * + * @note It always writes a full byte, the alternatives 'bit set' and + * 'bit clear' aren't supported. */ int mci_switch(struct mci *mci, unsigned index, unsigned value) { + unsigned int status; struct mci_cmd cmd; + int ret; mci_setup_cmd(&cmd, MMC_CMD_SWITCH, (MMC_SWITCH_MODE_WRITE_BYTE << 24) | @@ -406,19 +526,47 @@ int mci_switch(struct mci *mci, unsigned index, unsigned value) (value << 8), MMC_RSP_R1b); - return mci_send_cmd(mci, &cmd, NULL); + ret = mci_send_cmd(mci, &cmd, NULL); + if (ret) + return ret; + + ret = mci_send_status(mci, &status); + if (ret) + return ret; + + if (status & R1_SWITCH_ERROR) + return -EIO; + + return 0; +} + +u8 *mci_get_ext_csd(struct mci *mci) +{ + u8 *ext_csd; + int ret; + + ext_csd = xmalloc(512); + + ret = mci_send_ext_csd(mci, ext_csd); + if (ret) { + printf("Failure to read EXT_CSD register\n"); + free(ext_csd); + return ERR_PTR(-EIO); + } + + return ext_csd; } -static int mci_calc_blk_cnt(uint64_t cap, unsigned shift) +static blkcnt_t mci_calc_blk_cnt(blkcnt_t cap, unsigned shift) { - unsigned ret = cap >> shift; + blkcnt_t ret = cap >> shift; if (ret > 0x7fffffff) { pr_warn("Limiting card size due to 31 bit contraints\n"); return 0x7fffffff; } - return (int)ret; + return ret; } static void mci_part_add(struct mci *mci, uint64_t size, @@ -437,13 +585,78 @@ static void mci_part_add(struct mci *mci, uint64_t size, part->part_cfg = part_cfg; part->idx = idx; - if (area_type == MMC_BLK_DATA_AREA_MAIN) - part->blk.cdev.device_node = mci->host->hw_dev->device_node; + if (area_type == MMC_BLK_DATA_AREA_MAIN) { + cdev_set_of_node(&part->blk.cdev, mci->host->hw_dev->of_node); + part->blk.cdev.flags |= DEVFS_IS_MCI_MAIN_PART_DEV; + } mci->nr_parts++; } /** + * Read a value spread to three consecutive bytes in the ECSD information + * @param[in] ecsd_info Information from the eMMC + * @param[in] idx The index where to start to read + * @return The GPP size in units of 'write protect group' size + * + * The value in the ECSD information block is meant in little endian + */ +static __maybe_unused unsigned mmc_extract_gpp_units(const char *ecsd_info, unsigned idx) +{ + unsigned val; + + val = ecsd_info[idx]; + val |= ecsd_info[idx + 1] << 8; + val |= ecsd_info[idx + 2] << 16; + + return val; +} + +/** + * Create and enable access to 'general purpose hardware partitions' on demand + * @param mci[in,out] MCI instance + * + * General Purpose hardware Partitions (aka GPPs) aren't enabled by default. Its + * up to the application to (one-time) setup the eMMC to provide GPPs. Since + * they aren't wildly used, enable access to them on demand only. + */ +static __maybe_unused void mmc_extract_gpp_partitions(struct mci *mci) +{ + uint64_t wpgs, part_size; + size_t idx; + char *name, *partname; + static const unsigned gpp_offsets[MMC_NUM_GP_PARTITION] = { + EXT_CSD_GP_SIZE_MULT0, EXT_CSD_GP_SIZE_MULT1, + EXT_CSD_GP_SIZE_MULT2, EXT_CSD_GP_SIZE_MULT3, }; + + if (!(mci->ext_csd[EXT_CSD_PARTITIONING_SUPPORT] & 0x01)) + return; /* no partitioning support */ + /* + * The size of GPPs is defined in units of 'write protect group' size. + * The 'write protect group' size is defined to: + * CSD_HC_ERASE_GRP_SIZE * CSD_HC_WP_GRP_SIZE * 512 kiB + */ + wpgs = mci->ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE]; + wpgs *= mci->ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; + wpgs *= SZ_512K; + + /* up to four GPPs can be enabled. */ + for (idx = 0; idx < ARRAY_SIZE(gpp_offsets); idx++) { + part_size = mmc_extract_gpp_units(mci->ext_csd, gpp_offsets[idx]); + if (part_size == 0) + continue; + /* Convert to bytes */ + part_size *= wpgs; + + partname = xasprintf("gpp%zu", idx); + name = xasprintf("%s.%s", mci->cdevname, partname); + /* TODO read-only flag */ + mci_part_add(mci, part_size, EXT_CSD_PART_CONFIG_ACC_GPP0 + idx, + name, partname, idx, false, MMC_BLK_DATA_AREA_GP); + } +} + +/** * Change transfer frequency for an MMC card * @param mci MCI instance * @return Transaction status (0 on success) @@ -470,7 +683,7 @@ static int mmc_change_freq(struct mci *mci) cardtype = mci->ext_csd[EXT_CSD_DEVICE_TYPE] & EXT_CSD_CARD_TYPE_MASK; - err = mci_switch(mci, EXT_CSD_HS_TIMING, 1); + err = mci_switch(mci, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS); if (err) { dev_dbg(&mci->dev, "MMC frequency changing failed: %d\n", err); @@ -491,11 +704,15 @@ static int mmc_change_freq(struct mci *mci) return 0; } - /* High Speed is set, there are two types: 52MHz and 26MHz */ - if (cardtype & EXT_CSD_CARD_TYPE_52) - mci->card_caps |= MMC_CAP_MMC_HIGHSPEED_52MHZ | MMC_CAP_MMC_HIGHSPEED; - else - mci->card_caps |= MMC_CAP_MMC_HIGHSPEED; + mci->card_caps |= MMC_CAP_MMC_HIGHSPEED; + + /* High Speed is set, there are three types: 26MHz, 52MHz, 52MHz DDR */ + if (cardtype & EXT_CSD_CARD_TYPE_52) { + mci->card_caps |= MMC_CAP_MMC_HIGHSPEED_52MHZ; + + if (cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V) + mci->card_caps |= MMC_CAP_MMC_3_3V_DDR | MMC_CAP_MMC_1_8V_DDR; + } if (IS_ENABLED(CONFIG_MCI_MMC_BOOT_PARTITIONS) && mci->ext_csd[EXT_CSD_REV] >= 3 && mci->ext_csd[EXT_CSD_BOOT_SIZE_MULT]) { @@ -516,8 +733,12 @@ static int mmc_change_freq(struct mci *mci) mci->ext_csd_part_config = mci->ext_csd[EXT_CSD_PARTITION_CONFIG]; mci->bootpart = (mci->ext_csd_part_config >> 3) & 0x7; + mci->boot_ack_enable = (mci->ext_csd_part_config >> 6) & 0x1; } + if (IS_ENABLED(CONFIG_MCI_MMC_GPP_PARTITIONS)) + mmc_extract_gpp_partitions(mci); + return 0; } @@ -675,6 +896,8 @@ static void mci_set_ios(struct mci *mci) }; host->set_ios(host, &ios); + + host->actual_clock = host->clock; } /** @@ -702,7 +925,7 @@ static void mci_set_clock(struct mci *mci, unsigned clock) * @param mci MCI instance * @param width New interface bit width (1, 4 or 8) */ -static void mci_set_bus_width(struct mci *mci, unsigned width) +static void mci_set_bus_width(struct mci *mci, enum mci_bus_width width) { struct mci_host *host = mci->host; @@ -893,7 +1116,7 @@ static void mci_extract_card_dsr_imp_from_csd(struct mci *mci) mci->dsr_imp = UNSTUFF_BITS(mci->csd, 76, 1); } -static int mmc_compare_ext_csds(struct mci *mci, unsigned bus_width) +static int mmc_compare_ext_csds(struct mci *mci, enum mci_bus_width bus_width) { u8 *bw_ext_csd; int err; @@ -1005,34 +1228,71 @@ static int mci_startup_sd(struct mci *mci) return 0; } -static int mci_startup_mmc(struct mci *mci) +static u32 mci_bus_width_ext_csd_bits(enum mci_bus_width bus_width) { - struct mci_host *host = mci->host; + switch (bus_width) { + case MMC_BUS_WIDTH_8: + return EXT_CSD_BUS_WIDTH_8; + case MMC_BUS_WIDTH_4: + return EXT_CSD_BUS_WIDTH_4; + case MMC_BUS_WIDTH_1: + default: + return EXT_CSD_BUS_WIDTH_1; + } +} + +static int mci_mmc_try_bus_width(struct mci *mci, enum mci_bus_width bus_width, + enum mci_timing timing) +{ + u32 ext_csd_bits; int err; - int idx = 0; - static unsigned ext_csd_bits[] = { - EXT_CSD_BUS_WIDTH_4, - EXT_CSD_BUS_WIDTH_8, - }; - static unsigned bus_widths[] = { - MMC_BUS_WIDTH_4, - MMC_BUS_WIDTH_8, - }; - /* if possible, speed up the transfer */ - if (mci_caps(mci) & MMC_CAP_MMC_HIGHSPEED) { - if (mci->card_caps & MMC_CAP_MMC_HIGHSPEED_52MHZ) - mci->tran_speed = 52000000; - else - mci->tran_speed = 26000000; + ext_csd_bits = mci_bus_width_ext_csd_bits(bus_width); - host->timing = MMC_TIMING_MMC_HS; + if (mci_timing_is_ddr(timing)) + ext_csd_bits |= EXT_CSD_DDR_FLAG; + + err = mci_switch(mci, EXT_CSD_BUS_WIDTH, ext_csd_bits); + if (err < 0) + goto out; + + mci->host->timing = timing; + mci_set_bus_width(mci, bus_width); + + switch (bus_width) { + case MMC_BUS_WIDTH_8: + mci->card_caps |= MMC_CAP_8_BIT_DATA; + break; + case MMC_BUS_WIDTH_4: + mci->card_caps |= MMC_CAP_4_BIT_DATA; + break; + default: + break; } - mci_set_clock(mci, mci->tran_speed); + err = mmc_compare_ext_csds(mci, bus_width); + if (err < 0) + goto out; + +out: + dev_dbg(&mci->dev, "Tried buswidth %u%s: %s\n", 1 << bus_width, + mci_timing_is_ddr(timing) ? " (DDR)" : "", err ? "failed" : "OK"); + + return err ?: bus_width; +} + +static int mci_mmc_select_bus_width(struct mci *mci) +{ + struct mci_host *host = mci->host; + int ret; + int idx = 0; + static enum mci_bus_width bus_widths[] = { + MMC_BUS_WIDTH_4, + MMC_BUS_WIDTH_8, + }; if (!(host->host_caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) - return 0; + return MMC_BUS_WIDTH_1; /* * Unlike SD, MMC cards dont have a configuration register to notify @@ -1044,7 +1304,6 @@ static int mci_startup_mmc(struct mci *mci) idx = 1; for (; idx >= 0; idx--) { - /* * Host is capable of 8bit transfer, then switch * the device to work in 8bit transfer mode. If the @@ -1052,23 +1311,264 @@ static int mci_startup_mmc(struct mci *mci) * 4bit transfer mode. On success set the corresponding * bus width on the host. */ - err = mci_switch(mci, EXT_CSD_BUS_WIDTH, ext_csd_bits[idx]); - if (err) { - if (idx == 0) - dev_warn(&mci->dev, "Changing MMC bus width failed: %d\n", err); - continue; - } + ret = mci_mmc_try_bus_width(mci, bus_widths[idx], host->timing); + if (ret > 0) + break; + } - mci_set_bus_width(mci, bus_widths[idx]); + return ret; +} - err = mmc_compare_ext_csds(mci, bus_widths[idx]); - if (!err) - break; +static int mci_mmc_select_hs_ddr(struct mci *mci) +{ + struct mci_host *host = mci->host; + int ret; + + /* + * barebox MCI core does not change voltage, so we don't know here + * if we should check for the 1.8v or 3.3v mode. Until we support + * higher speed modes that require voltage switching like HS200/HS400, + * let's just check for either bit. + */ + if (!(mci_caps(mci) & (MMC_CAP_MMC_1_8V_DDR | MMC_CAP_MMC_3_3V_DDR))) + return 0; + + ret = mci_mmc_try_bus_width(mci, host->bus_width, MMC_TIMING_MMC_DDR52); + if (ret < 0) + return mci_mmc_try_bus_width(mci, host->bus_width, MMC_TIMING_MMC_HS); + + /* Block length is fixed to 512 bytes while in DDR mode */ + mci->read_bl_len = SECTOR_SIZE; + mci->write_bl_len = SECTOR_SIZE; + + return 0; +} + +int mci_execute_tuning(struct mci *mci) +{ + struct mci_host *host = mci->host; + u32 opcode; + + if (!host->execute_tuning) + return 0; + + /* Tuning is only supported for MMC / HS200 */ + if (mmc_card_hs200(mci)) + opcode = MMC_SEND_TUNING_BLOCK_HS200; + else + return 0; + + return host->execute_tuning(host, opcode); +} + +int mci_send_abort_tuning(struct mci *mci, u32 opcode) +{ + struct mci_cmd cmd = {}; + + /* + * eMMC specification specifies that CMD12 can be used to stop a tuning + * command, but SD specification does not, so do nothing unless it is + * eMMC. + */ + if (opcode != MMC_SEND_TUNING_BLOCK_HS200) + return 0; + + cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION; + cmd.resp_type = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; + + return mci_send_cmd(mci, &cmd, NULL); +} +EXPORT_SYMBOL_GPL(mci_send_abort_tuning); + +static void mmc_select_max_dtr(struct mci *mci) +{ + u8 card_type = mci->ext_csd[EXT_CSD_DEVICE_TYPE]; + u32 caps2 = mci->host->caps2; + u32 caps = mci->card_caps; + unsigned int hs_max_dtr = 0; + unsigned int hs200_max_dtr = 0; + + if ((caps & MMC_CAP_MMC_HIGHSPEED) && + (card_type & EXT_CSD_CARD_TYPE_26)) { + hs_max_dtr = MMC_HIGH_26_MAX_DTR; + } + + if ((caps & MMC_CAP_MMC_HIGHSPEED) && + (card_type & EXT_CSD_CARD_TYPE_52)) { + hs_max_dtr = MMC_HIGH_52_MAX_DTR; + } + + if ((caps2 & MMC_CAP2_HS200_1_8V_SDR) && + (card_type & EXT_CSD_CARD_TYPE_HS200_1_8V)) { + hs200_max_dtr = MMC_HS200_MAX_DTR; + } + + if ((caps2 & MMC_CAP2_HS200_1_2V_SDR) && + (card_type & EXT_CSD_CARD_TYPE_HS200_1_2V)) { + hs200_max_dtr = MMC_HS200_MAX_DTR; } + mci->host->hs200_max_dtr = hs200_max_dtr; + mci->host->hs_max_dtr = hs_max_dtr; +} +/* + * For device supporting HS200 mode, the following sequence + * should be done before executing the tuning process. + * 1. set the desired bus width(4-bit or 8-bit, 1-bit is not supported) + * 2. switch to HS200 mode + * 3. set the clock to > 52Mhz and <=200MHz + */ +static int mmc_select_hs200(struct mci *mci) +{ + unsigned int old_timing, old_clock; + int err = -EINVAL; + u8 val; + + /* + * Set the bus width(4 or 8) with host's support and + * switch to HS200 mode if bus width is set successfully. + */ + /* find out maximum bus width and then try DDR if supported */ + err = mci_mmc_select_bus_width(mci); + if (err > 0) { + /* TODO actually set drive strength instead of 0. Currently unsupported. */ + val = EXT_CSD_TIMING_HS200 | 0 << EXT_CSD_DRV_STR_SHIFT; + err = mci_switch(mci, EXT_CSD_HS_TIMING, val); + if (err == -EIO) + return -EBADMSG; + if (err) + goto err; + + /* + * Bump to HS timing and frequency. Some cards don't handle + * SEND_STATUS reliably at the initial frequency. + * NB: We can't move to full (HS200) speeds until after we've + * successfully switched over. + */ + old_timing = mci->host->timing; + old_clock = mci->host->clock; + + mci->host->timing = MMC_TIMING_MMC_HS200; + mci_set_ios(mci); + mci_set_clock(mci, mci->host->hs_max_dtr); + + err = mci_switch_status(mci, true); + + /* + * mmc_select_timing() assumes timing has not changed if + * it is a switch error. + */ + if (err == -EBADMSG) { + mci->host->clock = old_clock; + mci->host->timing = old_timing; + mci_set_ios(mci); + } + } +err: + if (err) { + dev_err(&mci->dev, "%s failed, error %d\n", __func__, err); + } return err; } +/* + * Set the bus speed for the selected speed mode. + */ +static void mmc_set_bus_speed(struct mci *mci) +{ + unsigned int max_dtr = (unsigned int)-1; + + if (mmc_card_hs200(mci) && + max_dtr > mci->host->hs200_max_dtr) + max_dtr = mci->host->hs200_max_dtr; + else if (mmc_card_hs(mci) && max_dtr > mci->host->hs_max_dtr) + max_dtr = mci->host->hs_max_dtr; + else if (max_dtr > mci->tran_speed) + max_dtr = mci->tran_speed; + + mci_set_clock(mci, max_dtr); +} + +/* + * Activate HS200 or HS400ES mode if supported. + */ +int mmc_select_timing(struct mci *mci) +{ + unsigned int mmc_avail_type; + int err = 0; + + mmc_select_max_dtr(mci); + + mmc_avail_type = mci->ext_csd[EXT_CSD_DEVICE_TYPE] & EXT_CSD_CARD_TYPE_MASK; + if (mmc_avail_type & EXT_CSD_CARD_TYPE_HS200) { + err = mmc_select_hs200(mci); + if (err == -EBADMSG) + mmc_avail_type &= ~EXT_CSD_CARD_TYPE_HS200; + else + goto out; + } + +out: + if (err && err != -EBADMSG) + return err; + + /* + * Set the bus speed to the selected bus timing. + * If timing is not selected, backward compatible is the default. + */ + mmc_set_bus_speed(mci); + + return 0; +} + +int mmc_hs200_tuning(struct mci *mci) +{ + return mci_execute_tuning(mci); +} + +static int mci_startup_mmc(struct mci *mci) +{ + struct mci_host *host = mci->host; + int ret = 0; + + /* if possible, speed up the transfer */ + if (mci_caps(mci) & MMC_CAP_MMC_HIGHSPEED) { + if (mci->card_caps & MMC_CAP_MMC_HIGHSPEED_52MHZ) + mci->tran_speed = 52000000; + else + mci->tran_speed = 26000000; + + host->timing = MMC_TIMING_MMC_HS; + } + + if (IS_ENABLED(CONFIG_MCI_TUNING)) { + /* + * Select timing interface + */ + ret = mmc_select_timing(mci); + if (ret) + return ret; + + if (mmc_card_hs200(mci)) + ret = mmc_hs200_tuning(mci); + } + + if (ret || !IS_ENABLED(CONFIG_MCI_TUNING)) { + mci_set_clock(mci, mci->tran_speed); + + /* find out maximum bus width and then try DDR if supported */ + ret = mci_mmc_select_bus_width(mci); + if (ret > MMC_BUS_WIDTH_1 && mci->tran_speed == 52000000) + ret = mci_mmc_select_hs_ddr(mci); + + if (ret < 0) { + dev_warn(&mci->dev, "Changing MMC bus width failed: %d\n", ret); + } + } + + return ret; +} + /** * Scan the given host interfaces and detect connected MMC/SD cards * @param mci MCI instance @@ -1242,13 +1742,16 @@ static int sd_send_if_cond(struct mci *mci) return 0; } +/** + * Switch between hardware MMC partitions on demand + */ static int mci_blk_part_switch(struct mci_part *part) { struct mci *mci = part->mci; int ret; - if (!IS_ENABLED(CONFIG_MCI_MMC_BOOT_PARTITIONS)) - return 0; + if (!IS_ENABLED(CONFIG_MCI_MMC_BOOT_PARTITIONS) && !IS_ENABLED(CONFIG_MCI_MMC_GPP_PARTITIONS)) + return 0; /* no need */ if (mci->part_curr == part) return 0; @@ -1284,26 +1787,27 @@ static int mci_blk_part_switch(struct mci_part *part) * This routine expects the buffer has the correct size to read all data! */ static int __maybe_unused mci_sd_write(struct block_device *blk, - const void *buffer, int block, int num_blocks) + const void *buffer, sector_t block, blkcnt_t num_blocks) { struct mci_part *part = container_of(blk, struct mci_part, blk); struct mci *mci = part->mci; struct mci_host *host = mci->host; int rc; - unsigned max_req_block = num_blocks; - int write_block; + blkcnt_t max_req_block = num_blocks; + blkcnt_t write_block; if (mci->host->max_req_size) max_req_block = mci->host->max_req_size / mci->write_bl_len; mci_blk_part_switch(part); - if (host->card_write_protected && host->card_write_protected(host)) { + if (!host->disable_wp && + host->card_write_protected && host->card_write_protected(host)) { dev_err(&mci->dev, "card write protected\n"); return -EPERM; } - dev_dbg(&mci->dev, "%s: Write %d block(s), starting at %d\n", + dev_dbg(&mci->dev, "%s: Write %llu block(s), starting at %llu\n", __func__, num_blocks, block); if (mci->write_bl_len != SECTOR_SIZE) { @@ -1314,15 +1818,15 @@ static int __maybe_unused mci_sd_write(struct block_device *blk, /* size of the block number field in the MMC/SD command is 32 bit only */ if (block > MAX_BUFFER_NUMBER) { - dev_dbg(&mci->dev, "Cannot handle block number %d. Too large!\n", block); + dev_dbg(&mci->dev, "Cannot handle block number %llu. Too large!\n", block); return -EINVAL; } while (num_blocks) { - write_block = min_t(int, num_blocks, max_req_block); + write_block = min(num_blocks, max_req_block); rc = mci_block_write(mci, buffer, block, write_block); if (rc != 0) { - dev_dbg(&mci->dev, "Writing block %d failed with %d\n", block, rc); + dev_dbg(&mci->dev, "Writing block %llu failed with %d\n", block, rc); return rc; } num_blocks -= write_block; @@ -1343,13 +1847,13 @@ static int __maybe_unused mci_sd_write(struct block_device *blk, * * This routine expects the buffer has the correct size to store all data! */ -static int mci_sd_read(struct block_device *blk, void *buffer, int block, - int num_blocks) +static int mci_sd_read(struct block_device *blk, void *buffer, sector_t block, + blkcnt_t num_blocks) { struct mci_part *part = container_of(blk, struct mci_part, blk); struct mci *mci = part->mci; - unsigned max_req_block = num_blocks; - int read_block; + blkcnt_t max_req_block = num_blocks; + blkcnt_t read_block; int rc; if (mci->host->max_req_size) @@ -1357,25 +1861,25 @@ static int mci_sd_read(struct block_device *blk, void *buffer, int block, mci_blk_part_switch(part); - dev_dbg(&mci->dev, "%s: Read %d block(s), starting at %d\n", + dev_dbg(&mci->dev, "%s: Read %llu block(s), starting at %llu\n", __func__, num_blocks, block); - if (mci->read_bl_len != 512) { - dev_dbg(&mci->dev, "MMC/SD block size is not 512 bytes (its %u bytes instead)\n", - mci->read_bl_len); + if (mci->read_bl_len != SECTOR_SIZE) { + dev_dbg(&mci->dev, "MMC/SD block size is not %d bytes (its %u bytes instead)\n", + SECTOR_SIZE, mci->read_bl_len); return -EINVAL; } if (block > MAX_BUFFER_NUMBER) { - dev_err(&mci->dev, "Cannot handle block number %d. Too large!\n", block); + dev_err(&mci->dev, "Cannot handle block number %llu. Too large!\n", block); return -EINVAL; } while (num_blocks) { - read_block = min_t(int, num_blocks, max_req_block); + read_block = min(num_blocks, max_req_block); rc = mci_read_block(mci, buffer, block, read_block); if (rc != 0) { - dev_dbg(&mci->dev, "Reading block %d failed with %d\n", block, rc); + dev_dbg(&mci->dev, "Reading block %llu failed with %d\n", block, rc); return rc; } num_blocks -= read_block; @@ -1488,6 +1992,10 @@ static const char *mci_timing_tostr(unsigned timing) return "MMC HS"; case MMC_TIMING_SD_HS: return "SD HS"; + case MMC_TIMING_MMC_DDR52: + return "MMC DDR52"; + case MMC_TIMING_MMC_HS200: + return "HS200"; default: return "unknown"; /* shouldn't happen */ } @@ -1495,19 +2003,22 @@ static const char *mci_timing_tostr(unsigned timing) static void mci_print_caps(unsigned caps) { - printf(" capabilities: %s%s%s%s%s\n", + printf(" capabilities: %s%s%s%s%s%s%s%s\n", caps & MMC_CAP_4_BIT_DATA ? "4bit " : "", caps & MMC_CAP_8_BIT_DATA ? "8bit " : "", caps & MMC_CAP_SD_HIGHSPEED ? "sd-hs " : "", caps & MMC_CAP_MMC_HIGHSPEED ? "mmc-hs " : "", - caps & MMC_CAP_MMC_HIGHSPEED_52MHZ ? "mmc-52MHz " : ""); + caps & MMC_CAP_MMC_HIGHSPEED_52MHZ ? "mmc-52MHz " : "", + caps & MMC_CAP_MMC_3_3V_DDR ? "ddr-3.3v " : "", + caps & MMC_CAP_MMC_1_8V_DDR ? "ddr-1.8v " : "", + caps & MMC_CAP_MMC_1_2V_DDR ? "ddr-1.2v " : ""); } /** * Output some valuable information when the user runs 'devinfo' on an MCI device * @param mci MCI device instance */ -static void mci_info(struct device_d *dev) +static void mci_info(struct device *dev) { struct mci *mci = container_of(dev, struct mci, dev); struct mci_host *host = mci->host; @@ -1533,7 +2044,9 @@ static void mci_info(struct device_d *dev) mci_print_caps(host->host_caps); printf("Card information:\n"); - printf(" Attached is a %s card\n", IS_SD(mci) ? "SD" : "MMC"); + printf(" Card type: %s\n", mci->sdio ? "SDIO" : IS_SD(mci) ? "SD" : "MMC"); + if (mci->sdio) + return; printf(" Version: %s\n", mci_version_string(mci)); printf(" Capacity: %u MiB\n", (unsigned)(mci->capacity >> 20)); @@ -1592,6 +2105,17 @@ static int mci_set_boot(struct param_d *param, void *priv) EXT_CSD_PARTITION_CONFIG, mci->ext_csd_part_config); } +static int mci_set_boot_ack(struct param_d *param, void *priv) +{ + struct mci *mci = priv; + + mci->ext_csd_part_config &= ~(0x1 << 6); + mci->ext_csd_part_config |= mci->boot_ack_enable << 6; + + return mci_switch(mci, + EXT_CSD_PARTITION_CONFIG, mci->ext_csd_part_config); +} + static const char *mci_boot_names[] = { "disabled", "boot0", @@ -1617,6 +2141,7 @@ static int mci_register_partition(struct mci_part *part) */ part->blk.dev = &mci->dev; part->blk.ops = &mci_ops; + part->blk.type = IS_SD(mci) ? BLK_TYPE_SD : BLK_TYPE_MMC; rc = blockdevice_register(&part->blk); if (rc != 0) { @@ -1625,7 +2150,7 @@ static int mci_register_partition(struct mci_part *part) } dev_info(&mci->dev, "registered %s\n", part->blk.cdev.name); - np = host->hw_dev->device_node; + np = host->hw_dev->of_node; /* create partitions on demand */ switch (part->area_type) { @@ -1635,21 +2160,17 @@ static int mci_register_partition(struct mci_part *part) else partnodename = "boot1-partitions"; - np = of_get_child_by_name(host->hw_dev->device_node, + np = of_get_child_by_name(host->hw_dev->of_node, partnodename); break; case MMC_BLK_DATA_AREA_MAIN: break; + case MMC_BLK_DATA_AREA_GP: + break; default: return 0; } - rc = parse_partition_table(&part->blk); - if (rc != 0) { - dev_warn(&mci->dev, "No partition table found\n"); - rc = 0; /* it's not a failure */ - } - if (np) { of_parse_partitions(&part->blk.cdev, np); @@ -1663,6 +2184,47 @@ static int mci_register_partition(struct mci_part *part) return 0; } +static int of_broken_cd_fixup(struct device_node *root, void *ctx) +{ + struct mci_host *host = ctx; + struct device *hw_dev = host->hw_dev; + struct device_node *np; + char *name; + + if (!host->broken_cd) + return 0; + + name = of_get_reproducible_name(hw_dev->of_node); + np = of_find_node_by_reproducible_name(root, name); + free(name); + if (!np) { + dev_warn(hw_dev, "Cannot find nodepath %pOF, cannot fixup\n", + hw_dev->of_node); + return -EINVAL; + } + + of_property_write_bool(np, "cd-gpios", false); + of_property_write_bool(np, "broken-cd", true); + + return 0; +} + +static int mci_get_partition_setting_completed(struct mci *mci) +{ + u8 *ext_csd; + int ret; + + ext_csd = mci_get_ext_csd(mci); + if (IS_ERR(ext_csd)) + return PTR_ERR(ext_csd); + + ret = ext_csd[EXT_CSD_PARTITION_SETTING_COMPLETED]; + + free(ext_csd); + + return ret; +} + /** * Probe an MCI card at the given host interface * @param mci MCI device instance @@ -1672,11 +2234,15 @@ static int mci_card_probe(struct mci *mci) { struct mci_host *host = mci->host; int i, rc, disknum, ret; + bool has_bootpart = false; - if (host->card_present && !host->card_present(host) && - !host->non_removable) { - dev_err(&mci->dev, "no card inserted\n"); - return -ENODEV; + if (host->card_present && !host->card_present(host) && !host->non_removable) { + if (!host->broken_cd) { + dev_err(&mci->dev, "no card inserted\n"); + return -ENODEV; + } + + dev_info(&mci->dev, "no card inserted (ignoring)\n"); } ret = regulator_enable(host->supply); @@ -1704,12 +2270,22 @@ static int mci_card_probe(struct mci *mci) goto on_error; } + if (!(host->caps2 & MMC_CAP2_NO_SDIO)) { + rc = sdio_send_op_cond(mci); + if (!rc) { + mci->ready_for_use = true; + mci->sdio = true; + dev_info(&mci->dev, "SDIO card detected, ignoring\n"); + return 0; + } + } + /* Check if this card can handle the "SD Card Physical Layer Specification 2.0" */ - if (!host->no_sd) { + if (!(host->caps2 & MMC_CAP2_NO_SD)) { rc = sd_send_if_cond(mci); rc = sd_send_op_cond(mci); } - if (host->no_sd || rc == -ETIMEDOUT) { + if ((host->caps2 & MMC_CAP2_NO_SD) || rc == -ETIMEDOUT) { /* If SD card initialization was skipped or if it timed out, * we check for an MMC card */ dev_dbg(&mci->dev, "Card seems to be a MultiMediaCard\n"); @@ -1726,6 +2302,11 @@ static int mci_card_probe(struct mci *mci) mci->cdevname = basprintf("disk%d", disknum); } + if (!sector_buf) + sector_buf = dma_alloc(SECTOR_SIZE); + + /* FIXME we don't check sector_buf against the device dma mask here */ + rc = mci_startup(mci); if (rc) { dev_warn(&mci->dev, "Card's startup fails with %d\n", rc); @@ -1741,12 +2322,27 @@ static int mci_card_probe(struct mci *mci) rc = mci_register_partition(part); if (IS_ENABLED(CONFIG_MCI_MMC_BOOT_PARTITIONS) && - part->area_type == MMC_BLK_DATA_AREA_BOOT && - !mci->param_boot) { - mci->param_boot = dev_add_param_enum(&mci->dev, "boot", - mci_set_boot, NULL, &mci->bootpart, - mci_boot_names, ARRAY_SIZE(mci_boot_names), mci); - } + part->area_type == MMC_BLK_DATA_AREA_BOOT) + has_bootpart = true; + } + + if (has_bootpart) { + mci->param_boot = + dev_add_param_enum(&mci->dev, "boot", mci_set_boot, + NULL, &mci->bootpart, mci_boot_names, + ARRAY_SIZE(mci_boot_names), mci); + + mci->param_boot_ack = + dev_add_param_bool(&mci->dev, "boot_ack", + mci_set_boot_ack, NULL, + &mci->boot_ack_enable, mci); + + ret = mci_get_partition_setting_completed(mci); + if (ret < 0) + dev_dbg(&mci->dev, + "Failed to determine EXT_CSD_PARTITION_SETTING_COMPLETED\n"); + else + dev_add_param_bool_fixed(&mci->dev, "partitioning_completed", ret); } dev_dbg(&mci->dev, "SD Card successfully added\n"); @@ -1787,15 +2383,6 @@ static int mci_set_probe(struct param_d *param, void *priv) return 0; } -static int mci_init(void) -{ - sector_buf = xmemalign(32, 512); - - return 0; -} - -device_initcall(mci_init); - int mci_detect_card(struct mci_host *host) { int rc; @@ -1807,13 +2394,25 @@ int mci_detect_card(struct mci_host *host) return mci_card_probe(host->mci); } -static int mci_detect(struct device_d *dev) +static int mci_detect(struct device *dev) { struct mci *mci = container_of(dev, struct mci, dev); return mci_detect_card(mci->host); } +static int mci_hw_detect(struct device *dev) +{ + struct mci *mci; + + list_for_each_entry(mci, &mci_list, list) { + if (dev == mci->host->hw_dev) + return mci_detect_card(mci->host); + } + + return -ENODEV; +} + /** * Create a new mci device (for convenience) * @param host mci_host for this MCI device @@ -1822,7 +2421,8 @@ static int mci_detect(struct device_d *dev) int mci_register(struct mci_host *host) { struct mci *mci; - struct param_d *param_probe; + struct device *hw_dev; + struct param_d *param; int ret; mci = xzalloc(sizeof(*mci)); @@ -1836,15 +2436,28 @@ int mci_register(struct mci_host *host) mci->dev.id = DEVICE_ID_DYNAMIC; } + hw_dev = host->hw_dev; mci->dev.platform_data = host; - mci->dev.parent = host->hw_dev; + mci->dev.parent = hw_dev; mci->host = host; host->mci = mci; mci->dev.detect = mci_detect; + if (!hw_dev->detect) + hw_dev->detect = mci_hw_detect; - host->supply = regulator_get(host->hw_dev, "vmmc"); + host->supply = regulator_get(hw_dev, "vmmc"); if (IS_ERR(host->supply)) { - dev_err(&mci->dev, "Failed to get 'vmmc' regulator.\n"); + /* + * If you know your regulator to be always online on boot, but + * can't easily add a barebox driver for it, you may use + * barebox,allow-dummy-supply in your board's regulator device + * tree node to side step this warning. + * + * If you run into this warning, because your regulator driver + * hasn't probed the device yet, consider enabling deep probe + * for your board, to probe dependencies on demand. + */ + dev_warn(hw_dev, "Failed to get 'vmmc' regulator (ignored).\n"); host->supply = NULL; } @@ -1852,17 +2465,26 @@ int mci_register(struct mci_host *host) if (ret) goto err_free; - dev_info(mci->host->hw_dev, "registered as %s\n", dev_name(&mci->dev)); + dev_info(hw_dev, "registered as %s\n", dev_name(&mci->dev)); - param_probe = dev_add_param_bool(&mci->dev, "probe", - mci_set_probe, NULL, &mci->probe, mci); + param = dev_add_param_bool(&mci->dev, "probe", mci_set_probe, NULL, + &mci->probe, mci); - if (IS_ERR(param_probe) && PTR_ERR(param_probe) != -ENOSYS) { - ret = PTR_ERR(param_probe); + if (IS_ERR(param) && PTR_ERR(param) != -ENOSYS) { + ret = PTR_ERR(param); dev_dbg(&mci->dev, "Failed to add 'probe' parameter to the MCI device\n"); goto err_unregister; } + param = dev_add_param_bool(&mci->dev, "broken_cd", NULL, NULL, + &host->broken_cd, mci); + + if (IS_ERR(param) && PTR_ERR(param) != -ENOSYS) { + ret = PTR_ERR(param); + dev_dbg(&mci->dev, "Failed to add 'broken_cd' parameter to the MCI device\n"); + goto err_unregister; + } + if (IS_ENABLED(CONFIG_MCI_INFO)) mci->dev.info = mci_info; @@ -1870,6 +2492,9 @@ int mci_register(struct mci_host *host) if (IS_ENABLED(CONFIG_MCI_STARTUP)) mci_card_probe(mci); + if (!(host->caps2 & MMC_CAP2_NO_SD) && dev_of_node(host->hw_dev)) + of_register_fixup(of_broken_cd_fixup, host); + list_add_tail(&mci->list, &mci_list); return 0; @@ -1936,13 +2561,40 @@ void mci_of_parse_node(struct mci_host *host, } } + host->broken_cd = of_property_read_bool(np, "broken-cd"); host->non_removable = of_property_read_bool(np, "non-removable"); - host->no_sd = of_property_read_bool(np, "no-sd"); + host->disable_wp = of_property_read_bool(np, "disable-wp"); + + if (of_property_read_bool(np, "full-pwr-cycle")) + host->caps2 |= MMC_CAP2_FULL_PWR_CYCLE; + if (of_property_read_bool(np, "full-pwr-cycle-in-suspend")) + host->caps2 |= MMC_CAP2_FULL_PWR_CYCLE_IN_SUSPEND; + if (of_property_read_bool(np, "no-sdio")) + host->caps2 |= MMC_CAP2_NO_SDIO; + if (of_property_read_bool(np, "no-sd")) + host->caps2 |= MMC_CAP2_NO_SD; + if (of_property_read_bool(np, "no-mmc")) + host->caps2 |= MMC_CAP2_NO_MMC; + if (IS_ENABLED(CONFIG_MCI_TUNING)) { + if (of_property_read_bool(np, "mmc-hs200-1_8v")) + host->caps2 |= MMC_CAP2_HS200_1_8V_SDR; + if (of_property_read_bool(np, "mmc-hs200-1_2v")) + host->caps2 |= MMC_CAP2_HS200_1_2V_SDR; + if (of_property_read_bool(np, "mmc-hs400-1_8v")) + host->caps2 |= MMC_CAP2_HS400_1_8V | MMC_CAP2_HS200_1_8V_SDR; + if (of_property_read_bool(np, "mmc-hs400-1_2v")) + host->caps2 |= MMC_CAP2_HS400_1_2V | MMC_CAP2_HS200_1_2V_SDR; + if (of_property_read_bool(np, "mmc-hs400-enhanced-strobe")) + host->caps2 |= MMC_CAP2_HS400_ES; + if (of_property_read_bool(np, "no-mmc-hs400")) + host->caps2 &= ~(MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V | + MMC_CAP2_HS400_ES); + } } void mci_of_parse(struct mci_host *host) { - return mci_of_parse_node(host, host->hw_dev->device_node); + return mci_of_parse_node(host, host->hw_dev->of_node); } struct mci *mci_get_device_by_name(const char *name) |