diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/core/core.c | 7 | ||||
-rw-r--r-- | drivers/mmc/core/host.c | 1 | ||||
-rw-r--r-- | drivers/mmc/core/queue.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/atmel-mci.c | 4 | ||||
-rw-r--r-- | drivers/mmc/host/bcm2835.c | 20 | ||||
-rw-r--r-- | drivers/mmc/host/cqhci-crypto.c | 38 | ||||
-rw-r--r-- | drivers/mmc/host/cqhci.h | 8 | ||||
-rw-r--r-- | drivers/mmc/host/dw_mmc-hi3798mv200.c | 8 | ||||
-rw-r--r-- | drivers/mmc/host/dw_mmc.c | 94 | ||||
-rw-r--r-- | drivers/mmc/host/dw_mmc.h | 27 | ||||
-rw-r--r-- | drivers/mmc/host/mtk-sd.c | 21 | ||||
-rw-r--r-- | drivers/mmc/host/mxcmmc.c | 8 | ||||
-rw-r--r-- | drivers/mmc/host/omap.c | 19 | ||||
-rw-r--r-- | drivers/mmc/host/rtsx_pci_sdmmc.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/rtsx_usb_sdmmc.c | 3 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-acpi.c | 20 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-brcmstb.c | 10 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-esdhc-imx.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-msm.c | 94 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-omap.c | 4 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-pxav3.c | 1 | ||||
-rw-r--r-- | drivers/mmc/host/tmio_mmc_core.c | 1 |
22 files changed, 291 insertions, 103 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index d996d39c0d6f..5241528f8b90 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -19,7 +19,6 @@ #include <linux/scatterlist.h> #include <linux/log2.h> #include <linux/pm_runtime.h> -#include <linux/pm_wakeup.h> #include <linux/suspend.h> #include <linux/fault-inject.h> #include <linux/random.h> @@ -557,8 +556,7 @@ int mmc_cqe_recovery(struct mmc_host *host) memset(&cmd, 0, sizeof(cmd)); cmd.opcode = MMC_STOP_TRANSMISSION; - cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; - cmd.flags &= ~MMC_RSP_CRC; /* Ignore CRC */ + cmd.flags = MMC_RSP_R1B_NO_CRC | MMC_CMD_AC; /* Ignore CRC */ cmd.busy_timeout = MMC_CQE_RECOVERY_TIMEOUT; mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); @@ -567,8 +565,7 @@ int mmc_cqe_recovery(struct mmc_host *host) memset(&cmd, 0, sizeof(cmd)); cmd.opcode = MMC_CMDQ_TASK_MGMT; cmd.arg = 1; /* Discard entire queue */ - cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; - cmd.flags &= ~MMC_RSP_CRC; /* Ignore CRC */ + cmd.flags = MMC_RSP_R1B_NO_CRC | MMC_CMD_AC; /* Ignore CRC */ cmd.busy_timeout = MMC_CQE_RECOVERY_TIMEOUT; err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 48bda70145ee..bdb22998357e 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -14,7 +14,6 @@ #include <linux/idr.h> #include <linux/of.h> #include <linux/pagemap.h> -#include <linux/pm_wakeup.h> #include <linux/export.h> #include <linux/leds.h> #include <linux/slab.h> diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c index 4d6844261912..ab662f502fe7 100644 --- a/drivers/mmc/core/queue.c +++ b/drivers/mmc/core/queue.c @@ -441,7 +441,7 @@ struct gendisk *mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, else mq->tag_set.queue_depth = MMC_QUEUE_DEPTH; mq->tag_set.numa_node = NUMA_NO_NODE; - mq->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING; + mq->tag_set.flags = BLK_MQ_F_BLOCKING; mq->tag_set.nr_hw_queues = 1; mq->tag_set.cmd_size = sizeof(struct mmc_queue_req); mq->tag_set.driver_data = mq; diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index fc360902729d..24fffc702a94 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -2499,8 +2499,10 @@ static int atmci_probe(struct platform_device *pdev) /* Get MCI capabilities and set operations according to it */ atmci_get_cap(host); ret = atmci_configure_dma(host); - if (ret == -EPROBE_DEFER) + if (ret == -EPROBE_DEFER) { + clk_disable_unprepare(host->mck); goto err_dma_probe_defer; + } if (ret == 0) { host->prepare_data = &atmci_prepare_data_dma; host->submit_data = &atmci_submit_data_dma; diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c index 7847f0c8b465..e5f151d092cd 100644 --- a/drivers/mmc/host/bcm2835.c +++ b/drivers/mmc/host/bcm2835.c @@ -1343,6 +1343,25 @@ static int bcm2835_add_host(struct bcm2835_host *host) return 0; } +static int bcm2835_suspend(struct device *dev) +{ + struct bcm2835_host *host = dev_get_drvdata(dev); + + clk_disable_unprepare(host->clk); + + return 0; +} + +static int bcm2835_resume(struct device *dev) +{ + struct bcm2835_host *host = dev_get_drvdata(dev); + + return clk_prepare_enable(host->clk); +} + +static DEFINE_SIMPLE_DEV_PM_OPS(bcm2835_pm_ops, bcm2835_suspend, + bcm2835_resume); + static int bcm2835_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -1471,6 +1490,7 @@ static struct platform_driver bcm2835_driver = { .name = "sdhost-bcm2835", .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = bcm2835_match, + .pm = pm_ptr(&bcm2835_pm_ops), }, }; module_platform_driver(bcm2835_driver); diff --git a/drivers/mmc/host/cqhci-crypto.c b/drivers/mmc/host/cqhci-crypto.c index d5f4b6972f63..cb8044093402 100644 --- a/drivers/mmc/host/cqhci-crypto.c +++ b/drivers/mmc/host/cqhci-crypto.c @@ -25,22 +25,16 @@ static const struct cqhci_crypto_alg_entry { static inline struct cqhci_host * cqhci_host_from_crypto_profile(struct blk_crypto_profile *profile) { - struct mmc_host *mmc = - container_of(profile, struct mmc_host, crypto_profile); - - return mmc->cqe_private; + return mmc_from_crypto_profile(profile)->cqe_private; } -static int cqhci_crypto_program_key(struct cqhci_host *cq_host, - const union cqhci_crypto_cfg_entry *cfg, - int slot) +static void cqhci_crypto_program_key(struct cqhci_host *cq_host, + const union cqhci_crypto_cfg_entry *cfg, + int slot) { u32 slot_offset = cq_host->crypto_cfg_register + slot * sizeof(*cfg); int i; - if (cq_host->ops->program_key) - return cq_host->ops->program_key(cq_host, cfg, slot); - /* Clear CFGE */ cqhci_writel(cq_host, 0, slot_offset + 16 * sizeof(cfg->reg_val[0])); @@ -55,7 +49,6 @@ static int cqhci_crypto_program_key(struct cqhci_host *cq_host, /* Write dword 16, which includes the new value of CFGE */ cqhci_writel(cq_host, le32_to_cpu(cfg->reg_val[16]), slot_offset + 16 * sizeof(cfg->reg_val[0])); - return 0; } static int cqhci_crypto_keyslot_program(struct blk_crypto_profile *profile, @@ -72,7 +65,6 @@ static int cqhci_crypto_keyslot_program(struct blk_crypto_profile *profile, int i; int cap_idx = -1; union cqhci_crypto_cfg_entry cfg = {}; - int err; BUILD_BUG_ON(CQHCI_CRYPTO_KEY_SIZE_INVALID != 0); for (i = 0; i < cq_host->crypto_capabilities.num_crypto_cap; i++) { @@ -99,10 +91,10 @@ static int cqhci_crypto_keyslot_program(struct blk_crypto_profile *profile, memcpy(cfg.crypto_key, key->raw, key->size); } - err = cqhci_crypto_program_key(cq_host, &cfg, slot); + cqhci_crypto_program_key(cq_host, &cfg, slot); memzero_explicit(&cfg, sizeof(cfg)); - return err; + return 0; } static int cqhci_crypto_clear_keyslot(struct cqhci_host *cq_host, int slot) @@ -113,7 +105,8 @@ static int cqhci_crypto_clear_keyslot(struct cqhci_host *cq_host, int slot) */ union cqhci_crypto_cfg_entry cfg = {}; - return cqhci_crypto_program_key(cq_host, &cfg, slot); + cqhci_crypto_program_key(cq_host, &cfg, slot); + return 0; } static int cqhci_crypto_keyslot_evict(struct blk_crypto_profile *profile, @@ -170,7 +163,6 @@ int cqhci_crypto_init(struct cqhci_host *cq_host) struct mmc_host *mmc = cq_host->mmc; struct device *dev = mmc_dev(mmc); struct blk_crypto_profile *profile = &mmc->crypto_profile; - unsigned int num_keyslots; unsigned int cap_idx; enum blk_crypto_mode_num blk_mode_num; unsigned int slot; @@ -180,6 +172,9 @@ int cqhci_crypto_init(struct cqhci_host *cq_host) !(cqhci_readl(cq_host, CQHCI_CAP) & CQHCI_CAP_CS)) goto out; + if (cq_host->ops->uses_custom_crypto_profile) + goto profile_initialized; + cq_host->crypto_capabilities.reg_val = cpu_to_le32(cqhci_readl(cq_host, CQHCI_CCAP)); @@ -198,9 +193,8 @@ int cqhci_crypto_init(struct cqhci_host *cq_host) * CCAP.CFGC is off by one, so the actual number of crypto * configurations (a.k.a. keyslots) is CCAP.CFGC + 1. */ - num_keyslots = cq_host->crypto_capabilities.config_count + 1; - - err = devm_blk_crypto_profile_init(dev, profile, num_keyslots); + err = devm_blk_crypto_profile_init( + dev, profile, cq_host->crypto_capabilities.config_count + 1); if (err) goto out; @@ -228,9 +222,11 @@ int cqhci_crypto_init(struct cqhci_host *cq_host) cq_host->crypto_cap_array[cap_idx].sdus_mask * 512; } +profile_initialized: + /* Clear all the keyslots so that we start in a known state. */ - for (slot = 0; slot < num_keyslots; slot++) - cqhci_crypto_clear_keyslot(cq_host, slot); + for (slot = 0; slot < profile->num_slots; slot++) + profile->ll_ops.keyslot_evict(profile, NULL, slot); /* CQHCI crypto requires the use of 128-bit task descriptors. */ cq_host->caps |= CQHCI_TASK_DESC_SZ_128; diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h index fab9d74445ba..ce189a1866b9 100644 --- a/drivers/mmc/host/cqhci.h +++ b/drivers/mmc/host/cqhci.h @@ -289,13 +289,11 @@ struct cqhci_host_ops { u64 *data); void (*pre_enable)(struct mmc_host *mmc); void (*post_disable)(struct mmc_host *mmc); -#ifdef CONFIG_MMC_CRYPTO - int (*program_key)(struct cqhci_host *cq_host, - const union cqhci_crypto_cfg_entry *cfg, int slot); -#endif void (*set_tran_desc)(struct cqhci_host *cq_host, u8 **desc, dma_addr_t addr, int len, bool end, bool dma64); - +#ifdef CONFIG_MMC_CRYPTO + bool uses_custom_crypto_profile; +#endif }; static inline void cqhci_writel(struct cqhci_host *host, u32 val, int reg) diff --git a/drivers/mmc/host/dw_mmc-hi3798mv200.c b/drivers/mmc/host/dw_mmc-hi3798mv200.c index cce174b5249b..5791a975a944 100644 --- a/drivers/mmc/host/dw_mmc-hi3798mv200.c +++ b/drivers/mmc/host/dw_mmc-hi3798mv200.c @@ -181,7 +181,6 @@ static int dw_mci_hi3798mv200_init(struct dw_mci *host) { struct dw_mci_hi3798mv200_priv *priv; struct device_node *np = host->dev->of_node; - int ret; priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -199,15 +198,12 @@ static int dw_mci_hi3798mv200_init(struct dw_mci *host) return dev_err_probe(host->dev, PTR_ERR(priv->drive_clk), "failed to get enabled ciu-drive clock\n"); - priv->crg_reg = syscon_regmap_lookup_by_phandle(np, "hisilicon,sap-dll-reg"); + priv->crg_reg = syscon_regmap_lookup_by_phandle_args(np, "hisilicon,sap-dll-reg", + 1, &priv->sap_dll_offset); if (IS_ERR(priv->crg_reg)) return dev_err_probe(host->dev, PTR_ERR(priv->crg_reg), "failed to get CRG reg\n"); - ret = of_property_read_u32_index(np, "hisilicon,sap-dll-reg", 1, &priv->sap_dll_offset); - if (ret) - return dev_err_probe(host->dev, ret, "failed to get sample DLL register offset\n"); - host->priv = priv; return 0; } diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 3cbda98d08d2..74f224647bf1 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2579,6 +2579,91 @@ static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt) } } +static void dw_mci_push_data64_32(struct dw_mci *host, void *buf, int cnt) +{ + struct mmc_data *data = host->data; + int init_cnt = cnt; + + /* try and push anything in the part_buf */ + if (unlikely(host->part_buf_count)) { + int len = dw_mci_push_part_bytes(host, buf, cnt); + + buf += len; + cnt -= len; + + if (host->part_buf_count == 8) { + mci_fifo_l_writeq(host->fifo_reg, host->part_buf); + host->part_buf_count = 0; + } + } +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + if (unlikely((unsigned long)buf & 0x7)) { + while (cnt >= 8) { + u64 aligned_buf[16]; + int len = min(cnt & -8, (int)sizeof(aligned_buf)); + int items = len >> 3; + int i; + /* memcpy from input buffer into aligned buffer */ + memcpy(aligned_buf, buf, len); + buf += len; + cnt -= len; + /* push data from aligned buffer into fifo */ + for (i = 0; i < items; ++i) + mci_fifo_l_writeq(host->fifo_reg, aligned_buf[i]); + } + } else +#endif + { + u64 *pdata = buf; + + for (; cnt >= 8; cnt -= 8) + mci_fifo_l_writeq(host->fifo_reg, *pdata++); + buf = pdata; + } + /* put anything remaining in the part_buf */ + if (cnt) { + dw_mci_set_part_bytes(host, buf, cnt); + /* Push data if we have reached the expected data length */ + if ((data->bytes_xfered + init_cnt) == + (data->blksz * data->blocks)) + mci_fifo_l_writeq(host->fifo_reg, host->part_buf); + } +} + +static void dw_mci_pull_data64_32(struct dw_mci *host, void *buf, int cnt) +{ +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + if (unlikely((unsigned long)buf & 0x7)) { + while (cnt >= 8) { + /* pull data from fifo into aligned buffer */ + u64 aligned_buf[16]; + int len = min(cnt & -8, (int)sizeof(aligned_buf)); + int items = len >> 3; + int i; + + for (i = 0; i < items; ++i) + aligned_buf[i] = mci_fifo_l_readq(host->fifo_reg); + + /* memcpy from aligned buffer into output buffer */ + memcpy(buf, aligned_buf, len); + buf += len; + cnt -= len; + } + } else +#endif + { + u64 *pdata = buf; + + for (; cnt >= 8; cnt -= 8) + *pdata++ = mci_fifo_l_readq(host->fifo_reg); + buf = pdata; + } + if (cnt) { + host->part_buf = mci_fifo_l_readq(host->fifo_reg); + dw_mci_pull_final_bytes(host, buf, cnt); + } +} + static void dw_mci_pull_data(struct dw_mci *host, void *buf, int cnt) { int len; @@ -3379,8 +3464,13 @@ int dw_mci_probe(struct dw_mci *host) width = 16; host->data_shift = 1; } else if (i == 2) { - host->push_data = dw_mci_push_data64; - host->pull_data = dw_mci_pull_data64; + if ((host->quirks & DW_MMC_QUIRK_FIFO64_32)) { + host->push_data = dw_mci_push_data64_32; + host->pull_data = dw_mci_pull_data64_32; + } else { + host->push_data = dw_mci_push_data64; + host->pull_data = dw_mci_pull_data64; + } width = 64; host->data_shift = 3; } else { diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 6447b916990d..5463392dc811 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -281,6 +281,8 @@ struct dw_mci_board { /* Support for longer data read timeout */ #define DW_MMC_QUIRK_EXTENDED_TMOUT BIT(0) +/* Force 32-bit access to the FIFO */ +#define DW_MMC_QUIRK_FIFO64_32 BIT(1) #define DW_MMC_240A 0x240a #define DW_MMC_280A 0x280a @@ -472,6 +474,31 @@ struct dw_mci_board { #define mci_fifo_writel(__value, __reg) __raw_writel(__reg, __value) #define mci_fifo_writeq(__value, __reg) __raw_writeq(__reg, __value) +/* + * Some dw_mmc devices have 64-bit FIFOs, but expect them to be + * accessed using two 32-bit accesses. If such controller is used + * with a 64-bit kernel, this has to be done explicitly. + */ +static inline u64 mci_fifo_l_readq(void __iomem *addr) +{ + u64 ans; + u32 proxy[2]; + + proxy[0] = mci_fifo_readl(addr); + proxy[1] = mci_fifo_readl(addr + 4); + memcpy(&ans, proxy, 8); + return ans; +} + +static inline void mci_fifo_l_writeq(void __iomem *addr, u64 value) +{ + u32 proxy[2]; + + memcpy(proxy, &value, 8); + mci_fifo_writel(addr, proxy[0]); + mci_fifo_writel(addr + 4, proxy[1]); +} + /* Register access macros */ #define mci_readl(dev, reg) \ readl_relaxed((dev)->regs + SDMMC_##reg) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 5ab7a26529a0..345ea91629e0 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -416,6 +416,7 @@ struct mtk_mmc_compatible { u8 clk_div_bits; bool recheck_sdio_irq; bool hs400_tune; /* only used for MT8173 */ + bool needs_top_base; u32 pad_tune_reg; bool async_fifo; bool data_tune; @@ -589,6 +590,7 @@ static const struct mtk_mmc_compatible mt7986_compat = { .clk_div_bits = 12, .recheck_sdio_irq = true, .hs400_tune = false, + .needs_top_base = true, .pad_tune_reg = MSDC_PAD_TUNE0, .async_fifo = true, .data_tune = true, @@ -629,6 +631,7 @@ static const struct mtk_mmc_compatible mt8183_compat = { .clk_div_bits = 12, .recheck_sdio_irq = false, .hs400_tune = false, + .needs_top_base = true, .pad_tune_reg = MSDC_PAD_TUNE0, .async_fifo = true, .data_tune = true, @@ -655,6 +658,7 @@ static const struct mtk_mmc_compatible mt8196_compat = { .clk_div_bits = 12, .recheck_sdio_irq = false, .hs400_tune = false, + .needs_top_base = true, .pad_tune_reg = MSDC_PAD_TUNE0, .async_fifo = true, .data_tune = true, @@ -1099,11 +1103,12 @@ static inline u32 msdc_cmd_find_resp(struct msdc_host *host, u32 resp; switch (mmc_resp_type(cmd)) { - /* Actually, R1, R5, R6, R7 are the same */ + /* Actually, R1, R5, R6, R7 are the same */ case MMC_RSP_R1: resp = 0x1; break; case MMC_RSP_R1B: + case MMC_RSP_R1B_NO_CRC: resp = 0x7; break; case MMC_RSP_R2: @@ -1353,7 +1358,8 @@ static bool msdc_cmd_done(struct msdc_host *host, int events, * CRC error. */ msdc_reset_hw(host); - if (events & MSDC_INT_RSPCRCERR) { + if (events & MSDC_INT_RSPCRCERR && + mmc_resp_type(cmd) != MMC_RSP_R1B_NO_CRC) { cmd->error = -EILSEQ; host->error |= REQ_CMD_EIO; } else if (events & MSDC_INT_CMDTMO) { @@ -2894,9 +2900,13 @@ static int msdc_drv_probe(struct platform_device *pdev) if (IS_ERR(host->base)) return PTR_ERR(host->base); - host->top_base = devm_platform_ioremap_resource(pdev, 1); - if (IS_ERR(host->top_base)) - host->top_base = NULL; + host->dev_comp = of_device_get_match_data(&pdev->dev); + + if (host->dev_comp->needs_top_base) { + host->top_base = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(host->top_base)) + return PTR_ERR(host->top_base); + } ret = mmc_regulator_get_supply(mmc); if (ret) @@ -2958,7 +2968,6 @@ static int msdc_drv_probe(struct platform_device *pdev) msdc_of_property_parse(pdev, host); host->dev = &pdev->dev; - host->dev_comp = of_device_get_match_data(&pdev->dev); host->src_clk_freq = clk_get_rate(host->src_clk); /* Set host parameters to mmc */ mmc->ops = &mt_msdc_ops; diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index e7a286c3216f..0a9affd12532 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -995,7 +995,7 @@ static int mxcmci_probe(struct platform_device *pdev) struct mxcmci_host *host; struct resource *res; int ret = 0, irq; - bool dat3_card_detect = false; + bool dat3_card_detect; dma_cap_mask_t mask; struct imxmmc_platform_data *pdata = pdev->dev.platform_data; @@ -1048,9 +1048,9 @@ static int mxcmci_probe(struct platform_device *pdev) if (pdata) dat3_card_detect = pdata->dat3_card_detect; - else if (mmc_card_is_removable(mmc) - && !of_property_read_bool(pdev->dev.of_node, "cd-gpios")) - dat3_card_detect = true; + else + dat3_card_detect = mmc_card_is_removable(mmc) && + !of_property_present(pdev->dev.of_node, "cd-gpios"); ret = mmc_regulator_get_supply(mmc); if (ret) diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 62252ad4e20d..3cdb2fc44965 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -1272,19 +1272,25 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id) /* Check for some optional GPIO controls */ slot->vsd = devm_gpiod_get_index_optional(host->dev, "vsd", id, GPIOD_OUT_LOW); - if (IS_ERR(slot->vsd)) - return dev_err_probe(host->dev, PTR_ERR(slot->vsd), + if (IS_ERR(slot->vsd)) { + r = dev_err_probe(host->dev, PTR_ERR(slot->vsd), "error looking up VSD GPIO\n"); + goto err_free_host; + } slot->vio = devm_gpiod_get_index_optional(host->dev, "vio", id, GPIOD_OUT_LOW); - if (IS_ERR(slot->vio)) - return dev_err_probe(host->dev, PTR_ERR(slot->vio), + if (IS_ERR(slot->vio)) { + r = dev_err_probe(host->dev, PTR_ERR(slot->vio), "error looking up VIO GPIO\n"); + goto err_free_host; + } slot->cover = devm_gpiod_get_index_optional(host->dev, "cover", id, GPIOD_IN); - if (IS_ERR(slot->cover)) - return dev_err_probe(host->dev, PTR_ERR(slot->cover), + if (IS_ERR(slot->cover)) { + r = dev_err_probe(host->dev, PTR_ERR(slot->cover), "error looking up cover switch GPIO\n"); + goto err_free_host; + } host->slots[id] = slot; @@ -1344,6 +1350,7 @@ err_remove_slot_name: device_remove_file(&mmc->class_dev, &dev_attr_slot_name); err_remove_host: mmc_remove_host(mmc); +err_free_host: mmc_free_host(mmc); return r; } diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index 48d3b0aae5a0..0c6eb60a95fd 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c @@ -115,8 +115,6 @@ static int sd_response_type(struct mmc_command *cmd) return SD_RSP_TYPE_R0; case MMC_RSP_R1: return SD_RSP_TYPE_R1; - case MMC_RSP_R1_NO_CRC: - return SD_RSP_TYPE_R1 | SD_NO_CHECK_CRC7; case MMC_RSP_R1B: return SD_RSP_TYPE_R1b; case MMC_RSP_R2: diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c index 107c78df53cf..d229c2b83ea9 100644 --- a/drivers/mmc/host/rtsx_usb_sdmmc.c +++ b/drivers/mmc/host/rtsx_usb_sdmmc.c @@ -313,9 +313,6 @@ static void sd_send_cmd_get_rsp(struct rtsx_usb_sdmmc *host, case MMC_RSP_R1: rsp_type = SD_RSP_TYPE_R1; break; - case MMC_RSP_R1_NO_CRC: - rsp_type = SD_RSP_TYPE_R1 | SD_NO_CHECK_CRC7; - break; case MMC_RSP_R1B: rsp_type = SD_RSP_TYPE_R1b; break; diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index d1ce9193ece9..e6c5c82f64fa 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -822,8 +822,6 @@ static int sdhci_acpi_probe(struct platform_device *pdev) struct acpi_device *device; struct sdhci_acpi_host *c; struct sdhci_host *host; - struct resource *iomem; - resource_size_t len; size_t priv_size; int quirks = 0; int err; @@ -844,17 +842,6 @@ static int sdhci_acpi_probe(struct platform_device *pdev) if (sdhci_acpi_byt_defer(dev)) return -EPROBE_DEFER; - iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!iomem) - return -ENOMEM; - - len = resource_size(iomem); - if (len < 0x100) - dev_err(dev, "Invalid iomem size!\n"); - - if (!devm_request_mem_region(dev, iomem->start, len, dev_name(dev))) - return -ENOMEM; - priv_size = slot ? slot->priv_size : 0; host = sdhci_alloc_host(dev, sizeof(struct sdhci_acpi_host) + priv_size); if (IS_ERR(host)) @@ -876,10 +863,9 @@ static int sdhci_acpi_probe(struct platform_device *pdev) goto err_free; } - host->ioaddr = devm_ioremap(dev, iomem->start, - resource_size(iomem)); - if (host->ioaddr == NULL) { - err = -ENOMEM; + host->ioaddr = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(host->ioaddr)) { + err = PTR_ERR(host->ioaddr); goto err_free; } diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c index 0ef4d578ade8..48cdcba0f39c 100644 --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -503,8 +503,15 @@ static int sdhci_brcmstb_suspend(struct device *dev) struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host); + int ret; clk_disable_unprepare(priv->base_clk); + if (host->mmc->caps2 & MMC_CAP2_CQE) { + ret = cqhci_suspend(host->mmc); + if (ret) + return ret; + } + return sdhci_pltfm_suspend(dev); } @@ -529,6 +536,9 @@ static int sdhci_brcmstb_resume(struct device *dev) ret = clk_set_rate(priv->base_clk, priv->base_freq_hz); } + if (host->mmc->caps2 & MMC_CAP2_CQE) + ret = cqhci_resume(host->mmc); + return ret; } #endif diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index e23177ea9d91..ff78a7c6a04c 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -1648,7 +1648,7 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, * Retrieving and requesting the actual WP GPIO will happen * in the call to mmc_of_parse(). */ - if (of_property_read_bool(np, "wp-gpios")) + if (of_property_present(np, "wp-gpios")) boarddata->wp_type = ESDHC_WP_GPIO; of_property_read_u32(np, "fsl,tuning-step", &boarddata->tuning_step); diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 1fcaaf683d68..e3d39311fdc7 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -1856,12 +1856,19 @@ out: #ifdef CONFIG_MMC_CRYPTO +static const struct blk_crypto_ll_ops sdhci_msm_crypto_ops; /* forward decl */ + static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host, struct cqhci_host *cq_host) { struct mmc_host *mmc = msm_host->mmc; + struct blk_crypto_profile *profile = &mmc->crypto_profile; struct device *dev = mmc_dev(mmc); struct qcom_ice *ice; + union cqhci_crypto_capabilities caps; + union cqhci_crypto_cap_entry cap; + int err; + int i; if (!(cqhci_readl(cq_host, CQHCI_CAP) & CQHCI_CAP_CS)) return 0; @@ -1876,8 +1883,37 @@ static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host, return PTR_ERR_OR_ZERO(ice); msm_host->ice = ice; - mmc->caps2 |= MMC_CAP2_CRYPTO; + /* Initialize the blk_crypto_profile */ + + caps.reg_val = cpu_to_le32(cqhci_readl(cq_host, CQHCI_CCAP)); + + /* The number of keyslots supported is (CFGC+1) */ + err = devm_blk_crypto_profile_init(dev, profile, caps.config_count + 1); + if (err) + return err; + + profile->ll_ops = sdhci_msm_crypto_ops; + profile->max_dun_bytes_supported = 4; + profile->dev = dev; + + /* + * Currently this driver only supports AES-256-XTS. All known versions + * of ICE support it, but to be safe make sure it is really declared in + * the crypto capability registers. The crypto capability registers + * also give the supported data unit size(s). + */ + for (i = 0; i < caps.num_crypto_cap; i++) { + cap.reg_val = cpu_to_le32(cqhci_readl(cq_host, + CQHCI_CRYPTOCAP + + i * sizeof(__le32))); + if (cap.algorithm_id == CQHCI_CRYPTO_ALG_AES_XTS && + cap.key_size == CQHCI_CRYPTO_KEY_SIZE_256) + profile->modes_supported[BLK_ENCRYPTION_MODE_AES_256_XTS] |= + cap.sdus_mask * 512; + } + + mmc->caps2 |= MMC_CAP2_CRYPTO; return 0; } @@ -1903,35 +1939,55 @@ static __maybe_unused int sdhci_msm_ice_suspend(struct sdhci_msm_host *msm_host) return 0; } -/* - * Program a key into a QC ICE keyslot, or evict a keyslot. QC ICE requires - * vendor-specific SCM calls for this; it doesn't support the standard way. - */ -static int sdhci_msm_program_key(struct cqhci_host *cq_host, - const union cqhci_crypto_cfg_entry *cfg, - int slot) +static inline struct sdhci_msm_host * +sdhci_msm_host_from_crypto_profile(struct blk_crypto_profile *profile) { - struct sdhci_host *host = mmc_priv(cq_host->mmc); + struct mmc_host *mmc = mmc_from_crypto_profile(profile); + struct sdhci_host *host = mmc_priv(mmc); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); - union cqhci_crypto_cap_entry cap; - if (!(cfg->config_enable & CQHCI_CRYPTO_CONFIGURATION_ENABLE)) - return qcom_ice_evict_key(msm_host->ice, slot); + return msm_host; +} + +/* + * Program a key into a QC ICE keyslot. QC ICE requires a QC-specific SCM call + * for this; it doesn't support the standard way. + */ +static int sdhci_msm_ice_keyslot_program(struct blk_crypto_profile *profile, + const struct blk_crypto_key *key, + unsigned int slot) +{ + struct sdhci_msm_host *msm_host = + sdhci_msm_host_from_crypto_profile(profile); /* Only AES-256-XTS has been tested so far. */ - cap = cq_host->crypto_cap_array[cfg->crypto_cap_idx]; - if (cap.algorithm_id != CQHCI_CRYPTO_ALG_AES_XTS || - cap.key_size != CQHCI_CRYPTO_KEY_SIZE_256) - return -EINVAL; + if (key->crypto_cfg.crypto_mode != BLK_ENCRYPTION_MODE_AES_256_XTS) + return -EOPNOTSUPP; return qcom_ice_program_key(msm_host->ice, QCOM_ICE_CRYPTO_ALG_AES_XTS, QCOM_ICE_CRYPTO_KEY_SIZE_256, - cfg->crypto_key, - cfg->data_unit_size, slot); + key->raw, + key->crypto_cfg.data_unit_size / 512, + slot); } +static int sdhci_msm_ice_keyslot_evict(struct blk_crypto_profile *profile, + const struct blk_crypto_key *key, + unsigned int slot) +{ + struct sdhci_msm_host *msm_host = + sdhci_msm_host_from_crypto_profile(profile); + + return qcom_ice_evict_key(msm_host->ice, slot); +} + +static const struct blk_crypto_ll_ops sdhci_msm_crypto_ops = { + .keyslot_program = sdhci_msm_ice_keyslot_program, + .keyslot_evict = sdhci_msm_ice_keyslot_evict, +}; + #else /* CONFIG_MMC_CRYPTO */ static inline int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host, @@ -2037,7 +2093,7 @@ static const struct cqhci_host_ops sdhci_msm_cqhci_ops = { .enable = sdhci_msm_cqe_enable, .disable = sdhci_msm_cqe_disable, #ifdef CONFIG_MMC_CRYPTO - .program_key = sdhci_msm_program_key, + .uses_custom_crypto_profile = true, #endif }; diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c index 54d795205fb4..26a9a8b5682a 100644 --- a/drivers/mmc/host/sdhci-omap.c +++ b/drivers/mmc/host/sdhci-omap.c @@ -1339,8 +1339,8 @@ static int sdhci_omap_probe(struct platform_device *pdev) /* R1B responses is required to properly manage HW busy detection. */ mmc->caps |= MMC_CAP_NEED_RSP_BUSY; - /* Allow card power off and runtime PM for eMMC/SD card devices */ - mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_AGGRESSIVE_PM; + /* Enable SDIO card power off. */ + mmc->caps |= MMC_CAP_POWER_OFF_CARD; ret = sdhci_setup_host(host); if (ret) diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index 990723a008ae..3fb56face3d8 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -399,6 +399,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev) if (!IS_ERR(pxa->clk_core)) clk_prepare_enable(pxa->clk_core); + host->mmc->caps |= MMC_CAP_NEED_RSP_BUSY; /* enable 1/8V DDR capable */ host->mmc->caps |= MMC_CAP_1_8V_DDR; diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index 45a474ccab1c..04c1c54df791 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -297,7 +297,6 @@ static int tmio_mmc_start_command(struct tmio_mmc_host *host, switch (mmc_resp_type(cmd)) { case MMC_RSP_NONE: c |= RESP_NONE; break; case MMC_RSP_R1: - case MMC_RSP_R1_NO_CRC: c |= RESP_R1; break; case MMC_RSP_R1B: c |= RESP_R1B; break; case MMC_RSP_R2: c |= RESP_R2; break; |