From de208e40d9964d482346c6e2eb92db2d58b36aae Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Thu, 21 Feb 2019 10:02:14 +0800 Subject: [PATCH] mmc: porting legacy tactices into 4.19 Change-Id: Ieb0e609f5cad4e889be6194f8fd8a54057a1174b Signed-off-by: Shawn Lin --- drivers/mmc/core/block.c | 16 ++++++++++ drivers/mmc/core/core.c | 20 +++++++++++++ drivers/mmc/core/host.c | 53 +++++++++++++++++++++++++++++++++ drivers/mmc/host/Makefile | 1 + drivers/mmc/host/dw_mmc.c | 23 ++++++++++++++ drivers/mmc/host/rk_sdmmc_ops.c | 3 ++ include/linux/genhd.h | 1 + include/linux/mmc/host.h | 5 ++++ 8 files changed, 122 insertions(+) diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index f6755b86eba2..2ab2eb6809e0 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -2915,6 +2915,7 @@ static void mmc_blk_remove_debugfs(struct mmc_card *card, #endif /* CONFIG_DEBUG_FS */ +extern struct mmc_card *this_card; static int mmc_blk_probe(struct mmc_card *card) { struct mmc_blk_data *md, *part_md; @@ -2943,6 +2944,15 @@ static int mmc_blk_probe(struct mmc_card *card) dev_set_drvdata(&card->dev, md); + #if defined(CONFIG_MMC_DW_ROCKCHIP) + if (card->host->restrict_caps & RESTRICT_CARD_TYPE_EMMC) { + this_card = card; + md->disk->emmc_disk = 1; + } else { + md->disk->emmc_disk = 0; + } + #endif + if (mmc_add_disk(md)) goto out; @@ -2979,6 +2989,12 @@ static void mmc_blk_remove(struct mmc_card *card) struct mmc_blk_data *md = dev_get_drvdata(&card->dev); mmc_blk_remove_debugfs(card, md); + + #if defined(CONFIG_MMC_DW_ROCKCHIP) + if (card->host->restrict_caps & RESTRICT_CARD_TYPE_EMMC) + this_card = NULL; + #endif + mmc_blk_remove_parts(card, md); pm_runtime_get_sync(&card->dev); if (md->part_curr != md->part_type) { diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 50a5c340307b..12c34e3109ea 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2505,6 +2505,7 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) * should be ignored by SD/eMMC cards. * Skip it if we already know that we do not support SDIO commands */ +#ifdef MMC_STANDARD_PROBE if (!(host->caps2 & MMC_CAP2_NO_SDIO)) sdio_reset(host); @@ -2525,7 +2526,26 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) if (!(host->caps2 & MMC_CAP2_NO_MMC)) if (!mmc_attach_mmc(host)) return 0; +#else + if (host->restrict_caps & RESTRICT_CARD_TYPE_SDIO) + sdio_reset(host); + mmc_go_idle(host); + + if (host->restrict_caps & + (RESTRICT_CARD_TYPE_SDIO | RESTRICT_CARD_TYPE_SD)) + mmc_send_if_cond(host, host->ocr_avail); + /* Order's important: probe SDIO, then SD, then MMC */ + if ((host->restrict_caps & RESTRICT_CARD_TYPE_SDIO) && + !mmc_attach_sdio(host)) + return 0; + if ((host->restrict_caps & RESTRICT_CARD_TYPE_SD) && + !mmc_attach_sd(host)) + return 0; + if ((host->restrict_caps & RESTRICT_CARD_TYPE_EMMC) && + !mmc_attach_mmc(host)) + return 0; +#endif mmc_power_off(host); return -EIO; } diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index f3dc49fa078d..6fce0f1af4f4 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -332,6 +332,13 @@ int mmc_of_parse(struct mmc_host *host) "can't use fixed driver type, media is removable\n"); } + if (device_property_read_bool(dev, "supports-sd")) + host->restrict_caps |= RESTRICT_CARD_TYPE_SD; + if (device_property_read_bool(dev, "supports-sdio")) + host->restrict_caps |= RESTRICT_CARD_TYPE_SDIO; + if (device_property_read_bool(dev, "supports-emmc")) + host->restrict_caps |= RESTRICT_CARD_TYPE_EMMC; + host->dsr_req = !device_property_read_u32(dev, "dsr", &host->dsr); if (host->dsr_req && (host->dsr & ~0xffff)) { dev_err(host->parent, @@ -355,6 +362,7 @@ EXPORT_SYMBOL(mmc_of_parse); * * Initialise the per-host structure. */ +static struct mmc_host *primary_sdio_host; struct mmc_host *mmc_alloc_host(int extra, struct device *dev) { int err; @@ -444,6 +452,9 @@ int mmc_add_host(struct mmc_host *host) if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY)) mmc_register_pm_notifier(host); + if (host->restrict_caps & RESTRICT_CARD_TYPE_SDIO) + primary_sdio_host = host; + return 0; } @@ -487,3 +498,45 @@ void mmc_free_host(struct mmc_host *host) } EXPORT_SYMBOL(mmc_free_host); + +/** + * mmc_host_rescan - triger software rescan flow + * @host: mmc host + * + * rescan slot attach in the assigned host. + * If @host is NULL, default rescan primary_sdio_host + * saved by mmc_add_host(). + * OR, rescan host from argument. + * + */ +int mmc_host_rescan(struct mmc_host *host, int val, int is_cap_sdio_irq) +{ + if (NULL != primary_sdio_host) { + if (!host) + host = primary_sdio_host; + else + pr_info("%s: mmc_host_rescan pass in host from argument!\n", + mmc_hostname(host)); + } else { + pr_err("sdio: host isn't initialization successfully.\n"); + return -ENOMEDIUM; + } + + pr_info("%s:mmc host rescan start!\n", mmc_hostname(host)); + + /* 0: oob 1:cap-sdio-irq */ + if (is_cap_sdio_irq == 1) { + host->caps |= MMC_CAP_SDIO_IRQ; + } else if (is_cap_sdio_irq == 0) { + host->caps &= ~MMC_CAP_SDIO_IRQ; + } else { + dev_err(&host->class_dev, "sdio: host doesn't identify oob or sdio_irq mode!\n"); + return -ENOMEDIUM; + } + + if (!(host->caps & MMC_CAP_NONREMOVABLE) && host->ops->set_sdio_status) + host->ops->set_sdio_status(host, val); + + return 0; +} +EXPORT_SYMBOL(mmc_host_rescan); diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index ce8398e6f2c0..d9ec0e9fea8d 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -56,6 +56,7 @@ obj-$(CONFIG_MMC_DW_HI3798CV200) += dw_mmc-hi3798cv200.o obj-$(CONFIG_MMC_DW_K3) += dw_mmc-k3.o obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o obj-$(CONFIG_MMC_DW_ROCKCHIP) += dw_mmc-rockchip.o +obj-$(CONFIG_MMC_DW_ROCKCHIP) += rk_sdmmc_ops.o obj-$(CONFIG_MMC_DW_ZX) += dw_mmc-zx.o obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 80dc2fd6576c..fcb2eac056ef 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -964,6 +964,28 @@ static void dw_mci_post_req(struct mmc_host *mmc, data->host_cookie = COOKIE_UNMAPPED; } +static int dw_mci_set_sdio_status(struct mmc_host *mmc, int val) +{ + struct dw_mci_slot *slot = mmc_priv(mmc); + struct dw_mci *host = slot->host; + + if (!(mmc->restrict_caps & RESTRICT_CARD_TYPE_SDIO)) + return 0; + + spin_lock_bh(&host->lock); + + if (val) + set_bit(DW_MMC_CARD_PRESENT, &slot->flags); + else + clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); + + spin_unlock_bh(&host->lock); + + mmc_detect_change(slot->mmc, 20); + + return 0; +} + static int dw_mci_get_cd(struct mmc_host *mmc) { int present; @@ -1801,6 +1823,7 @@ static const struct mmc_host_ops dw_mci_ops = { .pre_req = dw_mci_pre_req, .post_req = dw_mci_post_req, .set_ios = dw_mci_set_ios, + .set_sdio_status = dw_mci_set_sdio_status, .get_ro = dw_mci_get_ro, .get_cd = dw_mci_get_cd, .hw_reset = dw_mci_hw_reset, diff --git a/drivers/mmc/host/rk_sdmmc_ops.c b/drivers/mmc/host/rk_sdmmc_ops.c index 32b1aa437b03..a234c65d34c9 100644 --- a/drivers/mmc/host/rk_sdmmc_ops.c +++ b/drivers/mmc/host/rk_sdmmc_ops.c @@ -22,6 +22,9 @@ #include #include #include +#include "../core/card.h" +#include "../core/core.h" +#include "../core/mmc_ops.h" #define BLKSZ 512 diff --git a/include/linux/genhd.h b/include/linux/genhd.h index f767293b00e6..50091bba1a2a 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -198,6 +198,7 @@ struct gendisk { struct request_queue *queue; void *private_data; + int emmc_disk; /* Flag for emmc devive */ int flags; struct rw_semaphore lookup_sem; struct kobject *slave_dir; diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index beed7121c781..9943c669563a 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -140,6 +140,7 @@ struct mmc_host_ops { /* Check if the card is pulling dat[0:3] low */ int (*card_busy)(struct mmc_host *host); + int (*set_sdio_status)(struct mmc_host *host, int val); /* The tuning command opcode value is different for SD and eMMC cards */ int (*execute_tuning)(struct mmc_host *host, u32 opcode); @@ -371,6 +372,10 @@ struct mmc_host { int fixed_drv_type; /* fixed driver type for non-removable media */ mmc_pm_flag_t pm_caps; /* supported pm features */ + u32 restrict_caps; /* Indicate slot specific card type */ +#define RESTRICT_CARD_TYPE_SD (1 << 0) /* Can support Secure-Digital Card */ +#define RESTRICT_CARD_TYPE_SDIO (1 << 1) /* Can support Secure-Digital I/O Card or Combo-Mem */ +#define RESTRICT_CARD_TYPE_EMMC (1 << 2) /* Can support embedded Multi-Media Card */ /* host specific block data */ unsigned int max_seg_size; /* see blk_queue_max_segment_size */