summaryrefslogtreecommitdiffstats
path: root/drivers/mci/mci-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mci/mci-core.c')
-rw-r--r--drivers/mci/mci-core.c958
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)