From 9481b45ca9b951e0ad406c9d1f6f90ad6ff56a7d Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Sat, 18 Jul 2020 11:06:14 +0200 Subject: [PATCH 01/91] mmc: sdhci_am654: Replace HTTP links with HTTPS ones Rationale: Reduces attack surface on kernel devs opening the links for MITM as HTTPS traffic is much harder to manipulate. Deterministic algorithm: For each file: If not .svg: For each line: If doesn't contain `\bxmlns\b`: For each link, `\bhttp://[^# \t\r\n]*(?:\w|/)`: If neither `\bgnu\.org/license`, nor `\bmozilla\.org/MPL\b`: If both the HTTP and HTTPS versions return 200 OK and serve the same content: Replace HTTP with HTTPS. Signed-off-by: Alexander A. Klimov Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20200718090614.88946-1-grandmaster@al2klimov.de Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci_am654.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index f9d24af12396..0f3ed716d3d2 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -2,7 +2,7 @@ /* * sdhci_am654.c - SDHCI driver for TI's AM654 SOCs * - * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com * */ #include From d99654f62362e08fb203bb9f5b6ffbd2c00ad8b6 Mon Sep 17 00:00:00 2001 From: Faiz Abbas Date: Sun, 2 Aug 2020 12:31:14 +0530 Subject: [PATCH 02/91] dt-bindings: mmc: sdhci-am654: Document bindings for the host controllers on TI's J7200 devices Add binding documentation for mmc host controllers present on TI's J7200 SOC Signed-off-by: Faiz Abbas Acked-by: Rob Herring Link: https://lore.kernel.org/r/20200802070114.9624-1-faiz_abbas@ti.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/sdhci-am654.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mmc/sdhci-am654.txt b/Documentation/devicetree/bindings/mmc/sdhci-am654.txt index 6d202f4d9249..b49cbfdd679f 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-am654.txt +++ b/Documentation/devicetree/bindings/mmc/sdhci-am654.txt @@ -12,6 +12,8 @@ Required Properties: "ti,am654-sdhci-5.1": SDHCI on AM654 device. "ti,j721e-sdhci-8bit": 8 bit SDHCI on J721E device. "ti,j721e-sdhci-4bit": 4 bit SDHCI on J721E device. + "ti,j7200-sdhci-8bit": 8 bit SDHCI on J7200 device. + "ti,j7200-sdhci-4bit": 4 bit SDHCI on J7200 device. - reg: Must be two entries. - The first should be the sdhci register space - The second should the subsystem/phy register space @@ -33,7 +35,9 @@ Required Properties: These bindings must be provided otherwise the driver will disable the corresponding speed mode (i.e. all nodes must provide at least -legacy) -Optional Properties (Required for ti,am654-sdhci-5.1 and ti,j721e-sdhci-8bit): +Optional Properties (Required for ti,am654-sdhci-5.1, + ti,j721e-sdhci-8bit, + ti,j7200-sdhci-8bit): - ti,trm-icp: DLL trim select - ti,driver-strength-ohm: driver strength in ohms. Valid values are 33, 40, 50, 66 and 100 ohms. From bb82d3b57c35eb91918964954e6c8efcc1018ce3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 4 Aug 2020 17:13:45 +0200 Subject: [PATCH 03/91] mmc: s3cmci: remove empty kerneldoc comment Remove empty comment to fix W=1 compile warning: drivers/mmc/host/s3cmci.c:400: warning: Cannot understand * on line 400 - I thought it was a doc line Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200804151345.28005-1-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/s3cmci.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 444b2769ae2c..b5df948f8155 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -396,9 +396,6 @@ static void s3cmci_enable_irq(struct s3cmci_host *host, bool more) local_irq_restore(flags); } -/** - * - */ static void s3cmci_disable_irq(struct s3cmci_host *host, bool transfer) { unsigned long flags; From ce54fb38fa4291af8b39c70b114bdd30aaf0fd59 Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Sat, 8 Aug 2020 11:45:02 +0000 Subject: [PATCH 04/91] mmc: Kconfig: Add RISCV and CSKY for MMC_DW Synopsys DesignWare MMC controller could be used in RISC-V and C-SKY architectures. Signed-off-by: Guo Ren Cc: Ulf Hansson Link: https://lore.kernel.org/r/1596887102-9743-1-git-send-email-guoren@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 9c89a5b780e8..10adaf91faaa 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -777,7 +777,7 @@ config MMC_CAVIUM_THUNDERX config MMC_DW tristate "Synopsys DesignWare Memory Card Interface" - depends on ARC || ARM || ARM64 || MIPS || COMPILE_TEST + depends on ARC || ARM || ARM64 || MIPS || RISCV || CSKY || COMPILE_TEST help This selects support for the Synopsys DesignWare Mobile Storage IP block, this provides host support for SD and MMC interfaces, in both From 9e1adca2019b8bff3da61baef7b42042e6aa9b01 Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Sun, 9 Aug 2020 20:20:01 +0100 Subject: [PATCH 05/91] dt-bindings: mmc: renesas,sdhi: Add r8a774e1 support Document SDHI controller for RZ/G2H (R8A774E1) SoC, which is compatible with R-Car Gen3 SoC family. Signed-off-by: Lad Prabhakar Reviewed-by: Marian-Cristian Rotariu Reviewed-by: Geert Uytterhoeven Acked-by: Rob Herring Link: https://lore.kernel.org/r/20200809192001.19156-1-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml index b4c3fd40caeb..6bbf29b5c239 100644 --- a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml +++ b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml @@ -50,6 +50,7 @@ properties: - renesas,sdhi-r8a774a1 # RZ/G2M - renesas,sdhi-r8a774b1 # RZ/G2N - renesas,sdhi-r8a774c0 # RZ/G2E + - renesas,sdhi-r8a774e1 # RZ/G2H - renesas,sdhi-r8a7795 # R-Car H3 - renesas,sdhi-r8a7796 # R-Car M3-W - renesas,sdhi-r8a77961 # R-Car M3-W+ From 309de450d78e9e83036f8b696596d8e7aa078f0d Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 10 Aug 2020 09:02:47 +0100 Subject: [PATCH 06/91] ms_block: fix spelling mistake "doesn'" -> "doesn't" There is a spelling mistake in a debug message. Fix it. Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20200810080247.47024-1-colin.king@canonical.com Signed-off-by: Ulf Hansson --- drivers/memstick/core/ms_block.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c index 178954228631..8004dd64d09a 100644 --- a/drivers/memstick/core/ms_block.c +++ b/drivers/memstick/core/ms_block.c @@ -1223,7 +1223,7 @@ static int msb_read_boot_blocks(struct msb_data *msb) } if (be16_to_cpu(page->header.block_id) != MS_BLOCK_BOOT_ID) { - dbg("the pba at %d doesn' contain boot block ID", pba); + dbg("the pba at %d doesn't contain boot block ID", pba); continue; } From 0ac4f496a2d46d5fe320d7034c792df4a5907c46 Mon Sep 17 00:00:00 2001 From: Haibo Chen Date: Tue, 11 Aug 2020 16:37:37 +0800 Subject: [PATCH 07/91] mmc: sdhci-esdhc-imx: Reset before sending tuning command for manual tuning According to IC suggestion, everytime before sending the tuning command, need to reset the usdhc, so to reset the tuning circuit, to let every tuning command work well for the manual tuning method. For standard tuning method, IC already add the reset operation in the hardware logic. Signed-off-by: Haibo Chen Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/1597135057-22272-1-git-send-email-haibo.chen@nxp.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-esdhc-imx.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index d738907a622f..0be334759c82 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -987,10 +987,20 @@ static int usdhc_execute_tuning(struct mmc_host *mmc, u32 opcode) static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val) { u32 reg; + u8 sw_rst; + int ret; /* FIXME: delay a bit for card to be ready for next tuning due to errors */ mdelay(1); + /* IC suggest to reset USDHC before every tuning command */ + esdhc_clrset_le(host, 0xff, SDHCI_RESET_ALL, SDHCI_SOFTWARE_RESET); + ret = readb_poll_timeout(host->ioaddr + SDHCI_SOFTWARE_RESET, sw_rst, + !(sw_rst & SDHCI_RESET_ALL), 10, 100); + if (ret == -ETIMEDOUT) + dev_warn(mmc_dev(host->mmc), + "warning! RESET_ALL never complete before sending tuning command\n"); + reg = readl(host->ioaddr + ESDHC_MIX_CTRL); reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL | ESDHC_MIX_CTRL_FBCLK_SEL; From 8ebe2607965d3e2dc02029e8c7dd35fbe508ffd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 27 Jul 2020 15:38:34 +0200 Subject: [PATCH 08/91] mmc: sdio: Check for CISTPL_VERS_1 buffer size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before parsing CISTPL_VERS_1 structure check that its size is at least two bytes to prevent buffer overflow. Signed-off-by: Pali Rohár Link: https://lore.kernel.org/r/20200727133837.19086-2-pali@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/core/sdio_cis.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c index e0655278c5c3..3efaa9534a77 100644 --- a/drivers/mmc/core/sdio_cis.c +++ b/drivers/mmc/core/sdio_cis.c @@ -26,6 +26,9 @@ static int cistpl_vers_1(struct mmc_card *card, struct sdio_func *func, unsigned i, nr_strings; char **buffer, *string; + if (size < 2) + return 0; + /* Find all null-terminated (including zero length) strings in the TPLLV1_INFO field. Trailing garbage is ignored. */ buf += 2; From 78366e9cbd7892ac3d321e62c4be7a7fe79a69ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 27 Jul 2020 15:38:35 +0200 Subject: [PATCH 09/91] mmc: sdio: Parse CISTPL_VERS_1 major and minor revision numbers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They should indicate compliance of standard. Signed-off-by: Pali Rohár Link: https://lore.kernel.org/r/20200727133837.19086-3-pali@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/core/sdio_cis.c | 8 ++++++++ include/linux/mmc/card.h | 2 ++ include/linux/mmc/sdio_func.h | 2 ++ 3 files changed, 12 insertions(+) diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c index 3efaa9534a77..44bea5e4aeda 100644 --- a/drivers/mmc/core/sdio_cis.c +++ b/drivers/mmc/core/sdio_cis.c @@ -23,12 +23,16 @@ static int cistpl_vers_1(struct mmc_card *card, struct sdio_func *func, const unsigned char *buf, unsigned size) { + u8 major_rev, minor_rev; unsigned i, nr_strings; char **buffer, *string; if (size < 2) return 0; + major_rev = buf[0]; + minor_rev = buf[1]; + /* Find all null-terminated (including zero length) strings in the TPLLV1_INFO field. Trailing garbage is ignored. */ buf += 2; @@ -60,9 +64,13 @@ static int cistpl_vers_1(struct mmc_card *card, struct sdio_func *func, } if (func) { + func->major_rev = major_rev; + func->minor_rev = minor_rev; func->num_info = nr_strings; func->info = (const char**)buffer; } else { + card->major_rev = major_rev; + card->minor_rev = minor_rev; card->num_info = nr_strings; card->info = (const char**)buffer; } diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 7d46411ffaa2..42df06c6b19c 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -297,6 +297,8 @@ struct mmc_card { struct sdio_cis cis; /* common tuple info */ struct sdio_func *sdio_func[SDIO_MAX_FUNCS]; /* SDIO functions (devices) */ struct sdio_func *sdio_single_irq; /* SDIO function when only one IRQ active */ + u8 major_rev; /* major revision number */ + u8 minor_rev; /* minor revision number */ unsigned num_info; /* number of info strings */ const char **info; /* info strings */ struct sdio_func_tuple *tuples; /* unknown common tuples */ diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h index fa2aaab5e57a..478855b8e406 100644 --- a/include/linux/mmc/sdio_func.h +++ b/include/linux/mmc/sdio_func.h @@ -51,6 +51,8 @@ struct sdio_func { u8 *tmpbuf; /* DMA:able scratch buffer */ + u8 major_rev; /* major revision number */ + u8 minor_rev; /* minor revision number */ unsigned num_info; /* number of info strings */ const char **info; /* info strings */ From b91ec1dc5c4afb29f08afe85cdd347306044d318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 27 Jul 2020 15:38:36 +0200 Subject: [PATCH 10/91] mmc: sdio: Extend sdio_config_attr macro and use it also for modalias MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This simplify code for generating sdio config attributes and allows easily define new sdio attributes. Signed-off-by: Pali Rohár Link: https://lore.kernel.org/r/20200727133837.19086-4-pali@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/core/sdio_bus.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 3cc928282af7..2384829c8fb2 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -28,29 +28,21 @@ #define to_sdio_driver(d) container_of(d, struct sdio_driver, drv) /* show configuration fields */ -#define sdio_config_attr(field, format_string) \ +#define sdio_config_attr(field, format_string, args...) \ static ssize_t \ field##_show(struct device *dev, struct device_attribute *attr, char *buf) \ { \ struct sdio_func *func; \ \ func = dev_to_sdio_func (dev); \ - return sprintf (buf, format_string, func->field); \ + return sprintf(buf, format_string, args); \ } \ static DEVICE_ATTR_RO(field) -sdio_config_attr(class, "0x%02x\n"); -sdio_config_attr(vendor, "0x%04x\n"); -sdio_config_attr(device, "0x%04x\n"); - -static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct sdio_func *func = dev_to_sdio_func (dev); - - return sprintf(buf, "sdio:c%02Xv%04Xd%04X\n", - func->class, func->vendor, func->device); -} -static DEVICE_ATTR_RO(modalias); +sdio_config_attr(class, "0x%02x\n", func->class); +sdio_config_attr(vendor, "0x%04x\n", func->vendor); +sdio_config_attr(device, "0x%04x\n", func->device); +sdio_config_attr(modalias, "sdio:c%02Xv%04Xd%04X\n", func->class, func->vendor, func->device); static struct attribute *sdio_dev_attrs[] = { &dev_attr_class.attr, From b698f6abb7b3de2fd04ebbb86527ab1ea95405e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 27 Jul 2020 15:38:37 +0200 Subject: [PATCH 11/91] mmc: sdio: Export SDIO revision and info strings to userspace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For SDIO functions, SDIO cards and SD COMBO cards are exported revision number and info strings from CISTPL_VERS_1 structure. Revision number should indicate compliance of standard and info strings should contain product information in same format as product information for PCMCIA cards. Product information for PCMCIA cards should contain following strings in this order: Manufacturer, Product Name, Lot number, Programming Conditions. Note that not all SDIO cards export all those info strings in that order as described in PCMCIA Metaformat Specification. Signed-off-by: Pali Rohár Link: https://lore.kernel.org/r/20200727133837.19086-5-pali@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/core/bus.c | 12 ++++++++++++ drivers/mmc/core/sd.c | 36 +++++++++++++++++++++++++++++++++--- drivers/mmc/core/sdio.c | 24 ++++++++++++++++++++++++ drivers/mmc/core/sdio_bus.c | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 70207f11a654..c2e70b757dd1 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -68,6 +68,7 @@ mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) { struct mmc_card *card = mmc_dev_to_card(dev); const char *type; + unsigned int i; int retval = 0; switch (card->type) { @@ -98,6 +99,17 @@ mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) card->cis.vendor, card->cis.device); if (retval) return retval; + + retval = add_uevent_var(env, "SDIO_REVISION=%u.%u", + card->major_rev, card->minor_rev); + if (retval) + return retval; + + for (i = 0; i < card->num_info; i++) { + retval = add_uevent_var(env, "SDIO_INFO%u=%s", i+1, card->info[i]); + if (retval) + return retval; + } } /* diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 5a2210c25aa7..429ca14fa7e1 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -709,10 +709,34 @@ static DEVICE_ATTR(dsr, S_IRUGO, mmc_dsr_show, NULL); MMC_DEV_ATTR(vendor, "0x%04x\n", card->cis.vendor); MMC_DEV_ATTR(device, "0x%04x\n", card->cis.device); +MMC_DEV_ATTR(revision, "%u.%u\n", card->major_rev, card->minor_rev); + +#define sdio_info_attr(num) \ +static ssize_t info##num##_show(struct device *dev, struct device_attribute *attr, char *buf) \ +{ \ + struct mmc_card *card = mmc_dev_to_card(dev); \ + \ + if (num > card->num_info) \ + return -ENODATA; \ + if (!card->info[num-1][0]) \ + return 0; \ + return sprintf(buf, "%s\n", card->info[num-1]); \ +} \ +static DEVICE_ATTR_RO(info##num) + +sdio_info_attr(1); +sdio_info_attr(2); +sdio_info_attr(3); +sdio_info_attr(4); static struct attribute *sd_std_attrs[] = { &dev_attr_vendor.attr, &dev_attr_device.attr, + &dev_attr_revision.attr, + &dev_attr_info1.attr, + &dev_attr_info2.attr, + &dev_attr_info3.attr, + &dev_attr_info4.attr, &dev_attr_cid.attr, &dev_attr_csd.attr, &dev_attr_scr.attr, @@ -738,9 +762,15 @@ static umode_t sd_std_is_visible(struct kobject *kobj, struct attribute *attr, struct device *dev = container_of(kobj, struct device, kobj); struct mmc_card *card = mmc_dev_to_card(dev); - /* CIS vendor and device ids are available only for Combo cards */ - if ((attr == &dev_attr_vendor.attr || attr == &dev_attr_device.attr) && - card->type != MMC_TYPE_SD_COMBO) + /* CIS vendor and device ids, revision and info string are available only for Combo cards */ + if ((attr == &dev_attr_vendor.attr || + attr == &dev_attr_device.attr || + attr == &dev_attr_revision.attr || + attr == &dev_attr_info1.attr || + attr == &dev_attr_info2.attr || + attr == &dev_attr_info3.attr || + attr == &dev_attr_info4.attr + ) && card->type != MMC_TYPE_SD_COMBO) return 0; return attr->mode; diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 7b40553d3934..694a212cbe25 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -29,12 +29,36 @@ MMC_DEV_ATTR(vendor, "0x%04x\n", card->cis.vendor); MMC_DEV_ATTR(device, "0x%04x\n", card->cis.device); +MMC_DEV_ATTR(revision, "%u.%u\n", card->major_rev, card->minor_rev); MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr); MMC_DEV_ATTR(rca, "0x%04x\n", card->rca); +#define sdio_info_attr(num) \ +static ssize_t info##num##_show(struct device *dev, struct device_attribute *attr, char *buf) \ +{ \ + struct mmc_card *card = mmc_dev_to_card(dev); \ + \ + if (num > card->num_info) \ + return -ENODATA; \ + if (!card->info[num-1][0]) \ + return 0; \ + return sprintf(buf, "%s\n", card->info[num-1]); \ +} \ +static DEVICE_ATTR_RO(info##num) + +sdio_info_attr(1); +sdio_info_attr(2); +sdio_info_attr(3); +sdio_info_attr(4); + static struct attribute *sdio_std_attrs[] = { &dev_attr_vendor.attr, &dev_attr_device.attr, + &dev_attr_revision.attr, + &dev_attr_info1.attr, + &dev_attr_info2.attr, + &dev_attr_info3.attr, + &dev_attr_info4.attr, &dev_attr_ocr.attr, &dev_attr_rca.attr, NULL, diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 2384829c8fb2..3d709029e07c 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -42,12 +42,36 @@ static DEVICE_ATTR_RO(field) sdio_config_attr(class, "0x%02x\n", func->class); sdio_config_attr(vendor, "0x%04x\n", func->vendor); sdio_config_attr(device, "0x%04x\n", func->device); +sdio_config_attr(revision, "%u.%u\n", func->major_rev, func->minor_rev); sdio_config_attr(modalias, "sdio:c%02Xv%04Xd%04X\n", func->class, func->vendor, func->device); +#define sdio_info_attr(num) \ +static ssize_t info##num##_show(struct device *dev, struct device_attribute *attr, char *buf) \ +{ \ + struct sdio_func *func = dev_to_sdio_func(dev); \ + \ + if (num > func->num_info) \ + return -ENODATA; \ + if (!func->info[num-1][0]) \ + return 0; \ + return sprintf(buf, "%s\n", func->info[num-1]); \ +} \ +static DEVICE_ATTR_RO(info##num) + +sdio_info_attr(1); +sdio_info_attr(2); +sdio_info_attr(3); +sdio_info_attr(4); + static struct attribute *sdio_dev_attrs[] = { &dev_attr_class.attr, &dev_attr_vendor.attr, &dev_attr_device.attr, + &dev_attr_revision.attr, + &dev_attr_info1.attr, + &dev_attr_info2.attr, + &dev_attr_info3.attr, + &dev_attr_info4.attr, &dev_attr_modalias.attr, NULL, }; @@ -98,6 +122,7 @@ static int sdio_bus_uevent(struct device *dev, struct kobj_uevent_env *env) { struct sdio_func *func = dev_to_sdio_func(dev); + unsigned int i; if (add_uevent_var(env, "SDIO_CLASS=%02X", func->class)) @@ -107,6 +132,15 @@ sdio_bus_uevent(struct device *dev, struct kobj_uevent_env *env) "SDIO_ID=%04X:%04X", func->vendor, func->device)) return -ENOMEM; + if (add_uevent_var(env, + "SDIO_REVISION=%u.%u", func->major_rev, func->minor_rev)) + return -ENOMEM; + + for (i = 0; i < func->num_info; i++) { + if (add_uevent_var(env, "SDIO_INFO%u=%s", i+1, func->info[i])) + return -ENOMEM; + } + if (add_uevent_var(env, "MODALIAS=sdio:c%02Xv%04Xd%04X", func->class, func->vendor, func->device)) From 81e41be92ad43b268910dcae78c5a72f79f3d467 Mon Sep 17 00:00:00 2001 From: Tobias Schramm Date: Fri, 14 Aug 2020 20:50:11 +0200 Subject: [PATCH 12/91] mmc: mmc_spi: fix timeout calculation Previously the cycle timeout was converted to a microsecond value but then incorrectly treated as a nanosecond timeout. This patch changes the code to convert both the nanosecond timeout and the cycle timeout to a microsecond value and use that directly. Signed-off-by: Tobias Schramm Link: https://lore.kernel.org/r/20200814185011.3252020-1-t.schramm@manjaro.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/mmc_spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 39bb1e30c2d7..f85e0ad896a9 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -882,9 +882,9 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, else clock_rate = spi->max_speed_hz; - timeout = data->timeout_ns + + timeout = data->timeout_ns / 1000 + data->timeout_clks * 1000000 / clock_rate; - timeout = usecs_to_jiffies((unsigned int)(timeout / 1000)) + 1; + timeout = usecs_to_jiffies((unsigned int)timeout) + 1; /* Handle scatterlist segments one at a time, with synch for * each 512-byte block From c92a6af6860c37dfa411049fdac45d225f0b424c Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 17 Aug 2020 13:58:38 +0200 Subject: [PATCH 13/91] mmc: test: remove ambiguity in test description MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When reading the test description, I thought a correction of the xfer_size was tested, which is not the case. It is tested that the xfer_size is correct. Use 'proper xfer_size' to remove this ambiguity. Signed-off-by: Wolfram Sang Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20200817115838.2981-1-wsa@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/core/mmc_test.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/core/mmc_test.c b/drivers/mmc/core/mmc_test.c index c21b3cb71775..152e7525ed33 100644 --- a/drivers/mmc/core/mmc_test.c +++ b/drivers/mmc/core/mmc_test.c @@ -2669,22 +2669,22 @@ static const struct mmc_test_case mmc_test_cases[] = { }, { - .name = "Correct xfer_size at write (start failure)", + .name = "Proper xfer_size at write (start failure)", .run = mmc_test_xfersize_write, }, { - .name = "Correct xfer_size at read (start failure)", + .name = "Proper xfer_size at read (start failure)", .run = mmc_test_xfersize_read, }, { - .name = "Correct xfer_size at write (midway failure)", + .name = "Proper xfer_size at write (midway failure)", .run = mmc_test_multi_xfersize_write, }, { - .name = "Correct xfer_size at read (midway failure)", + .name = "Proper xfer_size at read (midway failure)", .run = mmc_test_multi_xfersize_read, }, From 46f4a69ec8ed6ab9f6a6172afe50df792c8bc1b6 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 18 Aug 2020 13:45:08 +0300 Subject: [PATCH 14/91] mmc: sdhci: Add LTR support for some Intel BYT based controllers Some Intel BYT based host controllers support the setting of latency tolerance. Accordingly, implement the PM QoS ->set_latency_tolerance() callback. The raw register values are also exposed via debugfs. Intel EHL controllers require this support. Signed-off-by: Adrian Hunter Fixes: cb3a7d4a0aec4e ("mmc: sdhci-pci: Add support for Intel EHL") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20200818104508.7149-1-adrian.hunter@intel.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pci-core.c | 154 ++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index af413805bbf1..d0c8d39d5dbd 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -516,6 +518,8 @@ struct intel_host { bool rpm_retune_ok; u32 glk_rx_ctrl1; u32 glk_tun_val; + u32 active_ltr; + u32 idle_ltr; }; static const guid_t intel_dsm_guid = @@ -760,6 +764,108 @@ static int intel_execute_tuning(struct mmc_host *mmc, u32 opcode) return 0; } +#define INTEL_ACTIVELTR 0x804 +#define INTEL_IDLELTR 0x808 + +#define INTEL_LTR_REQ BIT(15) +#define INTEL_LTR_SCALE_MASK GENMASK(11, 10) +#define INTEL_LTR_SCALE_1US (2 << 10) +#define INTEL_LTR_SCALE_32US (3 << 10) +#define INTEL_LTR_VALUE_MASK GENMASK(9, 0) + +static void intel_cache_ltr(struct sdhci_pci_slot *slot) +{ + struct intel_host *intel_host = sdhci_pci_priv(slot); + struct sdhci_host *host = slot->host; + + intel_host->active_ltr = readl(host->ioaddr + INTEL_ACTIVELTR); + intel_host->idle_ltr = readl(host->ioaddr + INTEL_IDLELTR); +} + +static void intel_ltr_set(struct device *dev, s32 val) +{ + struct sdhci_pci_chip *chip = dev_get_drvdata(dev); + struct sdhci_pci_slot *slot = chip->slots[0]; + struct intel_host *intel_host = sdhci_pci_priv(slot); + struct sdhci_host *host = slot->host; + u32 ltr; + + pm_runtime_get_sync(dev); + + /* + * Program latency tolerance (LTR) accordingly what has been asked + * by the PM QoS layer or disable it in case we were passed + * negative value or PM_QOS_LATENCY_ANY. + */ + ltr = readl(host->ioaddr + INTEL_ACTIVELTR); + + if (val == PM_QOS_LATENCY_ANY || val < 0) { + ltr &= ~INTEL_LTR_REQ; + } else { + ltr |= INTEL_LTR_REQ; + ltr &= ~INTEL_LTR_SCALE_MASK; + ltr &= ~INTEL_LTR_VALUE_MASK; + + if (val > INTEL_LTR_VALUE_MASK) { + val >>= 5; + if (val > INTEL_LTR_VALUE_MASK) + val = INTEL_LTR_VALUE_MASK; + ltr |= INTEL_LTR_SCALE_32US | val; + } else { + ltr |= INTEL_LTR_SCALE_1US | val; + } + } + + if (ltr == intel_host->active_ltr) + goto out; + + writel(ltr, host->ioaddr + INTEL_ACTIVELTR); + writel(ltr, host->ioaddr + INTEL_IDLELTR); + + /* Cache the values into lpss structure */ + intel_cache_ltr(slot); +out: + pm_runtime_put_autosuspend(dev); +} + +static bool intel_use_ltr(struct sdhci_pci_chip *chip) +{ + switch (chip->pdev->device) { + case PCI_DEVICE_ID_INTEL_BYT_EMMC: + case PCI_DEVICE_ID_INTEL_BYT_EMMC2: + case PCI_DEVICE_ID_INTEL_BYT_SDIO: + case PCI_DEVICE_ID_INTEL_BYT_SD: + case PCI_DEVICE_ID_INTEL_BSW_EMMC: + case PCI_DEVICE_ID_INTEL_BSW_SDIO: + case PCI_DEVICE_ID_INTEL_BSW_SD: + return false; + default: + return true; + } +} + +static void intel_ltr_expose(struct sdhci_pci_chip *chip) +{ + struct device *dev = &chip->pdev->dev; + + if (!intel_use_ltr(chip)) + return; + + dev->power.set_latency_tolerance = intel_ltr_set; + dev_pm_qos_expose_latency_tolerance(dev); +} + +static void intel_ltr_hide(struct sdhci_pci_chip *chip) +{ + struct device *dev = &chip->pdev->dev; + + if (!intel_use_ltr(chip)) + return; + + dev_pm_qos_hide_latency_tolerance(dev); + dev->power.set_latency_tolerance = NULL; +} + static void byt_probe_slot(struct sdhci_pci_slot *slot) { struct mmc_host_ops *ops = &slot->host->mmc_host_ops; @@ -774,6 +880,43 @@ static void byt_probe_slot(struct sdhci_pci_slot *slot) ops->start_signal_voltage_switch = intel_start_signal_voltage_switch; device_property_read_u32(dev, "max-frequency", &mmc->f_max); + + if (!mmc->slotno) { + slot->chip->slots[mmc->slotno] = slot; + intel_ltr_expose(slot->chip); + } +} + +static void byt_add_debugfs(struct sdhci_pci_slot *slot) +{ + struct intel_host *intel_host = sdhci_pci_priv(slot); + struct mmc_host *mmc = slot->host->mmc; + struct dentry *dir = mmc->debugfs_root; + + if (!intel_use_ltr(slot->chip)) + return; + + debugfs_create_x32("active_ltr", 0444, dir, &intel_host->active_ltr); + debugfs_create_x32("idle_ltr", 0444, dir, &intel_host->idle_ltr); + + intel_cache_ltr(slot); +} + +static int byt_add_host(struct sdhci_pci_slot *slot) +{ + int ret = sdhci_add_host(slot->host); + + if (!ret) + byt_add_debugfs(slot); + return ret; +} + +static void byt_remove_slot(struct sdhci_pci_slot *slot, int dead) +{ + struct mmc_host *mmc = slot->host->mmc; + + if (!mmc->slotno) + intel_ltr_hide(slot->chip); } static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot) @@ -854,6 +997,8 @@ static int glk_emmc_add_host(struct sdhci_pci_slot *slot) if (ret) goto cleanup; + byt_add_debugfs(slot); + return 0; cleanup: @@ -1031,6 +1176,8 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_emmc = { #endif .allow_runtime_pm = true, .probe_slot = byt_emmc_probe_slot, + .add_host = byt_add_host, + .remove_slot = byt_remove_slot, .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | SDHCI_QUIRK_NO_LED, .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | @@ -1044,6 +1191,7 @@ static const struct sdhci_pci_fixes sdhci_intel_glk_emmc = { .allow_runtime_pm = true, .probe_slot = glk_emmc_probe_slot, .add_host = glk_emmc_add_host, + .remove_slot = byt_remove_slot, #ifdef CONFIG_PM_SLEEP .suspend = sdhci_cqhci_suspend, .resume = sdhci_cqhci_resume, @@ -1074,6 +1222,8 @@ static const struct sdhci_pci_fixes sdhci_ni_byt_sdio = { SDHCI_QUIRK2_PRESET_VALUE_BROKEN, .allow_runtime_pm = true, .probe_slot = ni_byt_sdio_probe_slot, + .add_host = byt_add_host, + .remove_slot = byt_remove_slot, .ops = &sdhci_intel_byt_ops, .priv_size = sizeof(struct intel_host), }; @@ -1091,6 +1241,8 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { SDHCI_QUIRK2_PRESET_VALUE_BROKEN, .allow_runtime_pm = true, .probe_slot = byt_sdio_probe_slot, + .add_host = byt_add_host, + .remove_slot = byt_remove_slot, .ops = &sdhci_intel_byt_ops, .priv_size = sizeof(struct intel_host), }; @@ -1110,6 +1262,8 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { .allow_runtime_pm = true, .own_cd_for_runtime_pm = true, .probe_slot = byt_sd_probe_slot, + .add_host = byt_add_host, + .remove_slot = byt_remove_slot, .ops = &sdhci_intel_byt_ops, .priv_size = sizeof(struct intel_host), }; From 6932794192f63c5e105eade19fba26b8ef29ec79 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 21 Aug 2020 08:35:33 +0200 Subject: [PATCH 15/91] mmc: core: Improve documentation of MMC_CAP_HW_RESET MMC_CAP_HW_RESET means that the controller is capable of resetting the eMMC device via RST_n signal, not a reset of the controller. Two drivers got this wrong, so let's make it more clear. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20200821063533.3771-1-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- include/linux/mmc/host.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index c5b6e97cb21a..799e23b0a23c 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -163,6 +163,7 @@ struct mmc_host_ops { int (*select_drive_strength)(struct mmc_card *card, unsigned int max_dtr, int host_drv, int card_drv, int *drv_type); + /* Reset the eMMC card via RST_n */ void (*hw_reset)(struct mmc_host *host); void (*card_event)(struct mmc_host *host); @@ -346,7 +347,7 @@ struct mmc_host { #define MMC_CAP_CD_WAKE (1 << 28) /* Enable card detect wake */ #define MMC_CAP_CMD_DURING_TFR (1 << 29) /* Commands during data transfer */ #define MMC_CAP_CMD23 (1 << 30) /* CMD23 supported. */ -#define MMC_CAP_HW_RESET (1 << 31) /* Hardware reset */ +#define MMC_CAP_HW_RESET (1 << 31) /* Reset the eMMC card via RST_n */ u32 caps2; /* More host capabilities */ From 87d7ad089b318b4f319bf57f1daa64eb6d1d10ad Mon Sep 17 00:00:00 2001 From: Madhuparna Bhowmik Date: Sat, 22 Aug 2020 11:45:28 +0530 Subject: [PATCH 16/91] mmc: via-sdmmc: Fix data race bug via_save_pcictrlreg() should be called with host->lock held as it writes to pm_pcictrl_reg, otherwise there can be a race condition between via_sd_suspend() and via_sdc_card_detect(). The same pattern is used in the function via_reset_pcictrl() as well, where via_save_pcictrlreg() is called with host->lock held. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Madhuparna Bhowmik Link: https://lore.kernel.org/r/20200822061528.7035-1-madhuparnabhowmik10@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/via-sdmmc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index 49dab9f42b6d..9b755ea0fa03 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c @@ -1257,11 +1257,14 @@ static void __maybe_unused via_init_sdc_pm(struct via_crdr_mmc_host *host) static int __maybe_unused via_sd_suspend(struct device *dev) { struct via_crdr_mmc_host *host; + unsigned long flags; host = dev_get_drvdata(dev); + spin_lock_irqsave(&host->lock, flags); via_save_pcictrlreg(host); via_save_sdcreg(host); + spin_unlock_irqrestore(&host->lock, flags); device_wakeup_enable(dev); From 061e4fbf6a64b6f870d95438932119a22a4b6321 Mon Sep 17 00:00:00 2001 From: Lars Povlsen Date: Tue, 25 Aug 2020 10:13:55 +0200 Subject: [PATCH 17/91] dt-bindings: mmc: Add Sparx5 SDHCI controller bindings The Sparx5 SDHCI controller is based on the Designware controller IP. Signed-off-by: Lars Povlsen Link: https://lore.kernel.org/r/20200825081357.32354-2-lars.povlsen@microchip.com Link: https://lore.kernel.org/r/20200826130106.22889-1-lars.povlsen@microchip.com Signed-off-by: Ulf Hansson --- .../mmc/microchip,dw-sparx5-sdhci.yaml | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 Documentation/devicetree/bindings/mmc/microchip,dw-sparx5-sdhci.yaml diff --git a/Documentation/devicetree/bindings/mmc/microchip,dw-sparx5-sdhci.yaml b/Documentation/devicetree/bindings/mmc/microchip,dw-sparx5-sdhci.yaml new file mode 100644 index 000000000000..55883290543b --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/microchip,dw-sparx5-sdhci.yaml @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/microchip,dw-sparx5-sdhci.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip Sparx5 Mobile Storage Host Controller Binding + +allOf: + - $ref: "mmc-controller.yaml" + +maintainers: + - Lars Povlsen + +# Everything else is described in the common file +properties: + compatible: + const: microchip,dw-sparx5-sdhci + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + description: + Handle to "core" clock for the sdhci controller. + + clock-names: + items: + - const: core + + microchip,clock-delay: + description: Delay clock to card to meet setup time requirements. + Each step increase by 1.25ns. + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 1 + maximum: 15 + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + +examples: + - | + #include + #include + sdhci0: mmc@600800000 { + compatible = "microchip,dw-sparx5-sdhci"; + reg = <0x00800000 0x1000>; + pinctrl-0 = <&emmc_pins>; + pinctrl-names = "default"; + clocks = <&clks CLK_ID_AUX1>; + clock-names = "core"; + assigned-clocks = <&clks CLK_ID_AUX1>; + assigned-clock-rates = <800000000>; + interrupts = ; + bus-width = <8>; + microchip,clock-delay = <10>; + }; From 43611afb6c178d4f07461fd4d4832e0da3762386 Mon Sep 17 00:00:00 2001 From: Lars Povlsen Date: Tue, 25 Aug 2020 10:13:56 +0200 Subject: [PATCH 18/91] mmc: sdhci-of-sparx5: Add Sparx5 SoC eMMC driver This adds the eMMC driver for the Sparx5 SoC. It is based upon the designware IP, but requires some extra initialization and quirks. Signed-off-by: Lars Povlsen Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/20200825081357.32354-3-lars.povlsen@microchip.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/Kconfig | 12 ++ drivers/mmc/host/Makefile | 1 + drivers/mmc/host/sdhci-of-sparx5.c | 269 +++++++++++++++++++++++++++++ 3 files changed, 282 insertions(+) create mode 100644 drivers/mmc/host/sdhci-of-sparx5.c diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 10adaf91faaa..0ef1992ece3b 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -213,6 +213,18 @@ config MMC_SDHCI_OF_DWCMSHC If you have a controller with this interface, say Y or M here. If unsure, say N. +config MMC_SDHCI_OF_SPARX5 + tristate "SDHCI OF support for the MCHP Sparx5 SoC" + depends on MMC_SDHCI_PLTFM + depends on ARCH_SPARX5 + help + This selects the Secure Digital Host Controller Interface (SDHCI) + found in the MCHP Sparx5 SoC. + + If you have a Sparx5 SoC with this interface, say Y or M here. + + If unsure, say N. + config MMC_SDHCI_CADENCE tristate "SDHCI support for the Cadence SD/SDIO/eMMC controller" depends on MMC_SDHCI_PLTFM diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 4d5bcb0144a0..451c25fc2c69 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -94,6 +94,7 @@ obj-$(CONFIG_MMC_SDHCI_OF_AT91) += sdhci-of-at91.o obj-$(CONFIG_MMC_SDHCI_OF_ESDHC) += sdhci-of-esdhc.o obj-$(CONFIG_MMC_SDHCI_OF_HLWD) += sdhci-of-hlwd.o obj-$(CONFIG_MMC_SDHCI_OF_DWCMSHC) += sdhci-of-dwcmshc.o +obj-$(CONFIG_MMC_SDHCI_OF_SPARX5) += sdhci-of-sparx5.o obj-$(CONFIG_MMC_SDHCI_BCM_KONA) += sdhci-bcm-kona.o obj-$(CONFIG_MMC_SDHCI_IPROC) += sdhci-iproc.o obj-$(CONFIG_MMC_SDHCI_MSM) += sdhci-msm.o diff --git a/drivers/mmc/host/sdhci-of-sparx5.c b/drivers/mmc/host/sdhci-of-sparx5.c new file mode 100644 index 000000000000..14b5dad6575a --- /dev/null +++ b/drivers/mmc/host/sdhci-of-sparx5.c @@ -0,0 +1,269 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * drivers/mmc/host/sdhci-of-sparx5.c + * + * MCHP Sparx5 SoC Secure Digital Host Controller Interface. + * + * Copyright (c) 2019 Microchip Inc. + * + * Author: Lars Povlsen + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "sdhci-pltfm.h" + +#define CPU_REGS_GENERAL_CTRL (0x22 * 4) +#define MSHC_DLY_CC_MASK GENMASK(16, 13) +#define MSHC_DLY_CC_SHIFT 13 +#define MSHC_DLY_CC_MAX 15 + +#define CPU_REGS_PROC_CTRL (0x2C * 4) +#define ACP_CACHE_FORCE_ENA BIT(4) +#define ACP_AWCACHE BIT(3) +#define ACP_ARCACHE BIT(2) +#define ACP_CACHE_MASK (ACP_CACHE_FORCE_ENA|ACP_AWCACHE|ACP_ARCACHE) + +#define MSHC2_VERSION 0x500 /* Off 0x140, reg 0x0 */ +#define MSHC2_TYPE 0x504 /* Off 0x140, reg 0x1 */ +#define MSHC2_EMMC_CTRL 0x52c /* Off 0x140, reg 0xB */ +#define MSHC2_EMMC_CTRL_EMMC_RST_N BIT(2) +#define MSHC2_EMMC_CTRL_IS_EMMC BIT(0) + +struct sdhci_sparx5_data { + struct sdhci_host *host; + struct regmap *cpu_ctrl; + int delay_clock; +}; + +#define BOUNDARY_OK(addr, len) \ + ((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1))) + +/* + * If DMA addr spans 128MB boundary, we split the DMA transfer into two + * so that each DMA transfer doesn't exceed the boundary. + */ +static void sdhci_sparx5_adma_write_desc(struct sdhci_host *host, void **desc, + dma_addr_t addr, int len, + unsigned int cmd) +{ + int tmplen, offset; + + if (likely(!len || BOUNDARY_OK(addr, len))) { + sdhci_adma_write_desc(host, desc, addr, len, cmd); + return; + } + + pr_debug("%s: write_desc: splitting dma len %d, offset 0x%0llx\n", + mmc_hostname(host->mmc), len, addr); + + offset = addr & (SZ_128M - 1); + tmplen = SZ_128M - offset; + sdhci_adma_write_desc(host, desc, addr, tmplen, cmd); + + addr += tmplen; + len -= tmplen; + sdhci_adma_write_desc(host, desc, addr, len, cmd); +} + +static void sparx5_set_cacheable(struct sdhci_host *host, u32 value) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_sparx5_data *sdhci_sparx5 = sdhci_pltfm_priv(pltfm_host); + + pr_debug("%s: Set Cacheable = 0x%x\n", mmc_hostname(host->mmc), value); + + /* Update ACP caching attributes in HW */ + regmap_update_bits(sdhci_sparx5->cpu_ctrl, + CPU_REGS_PROC_CTRL, ACP_CACHE_MASK, value); +} + +static void sparx5_set_delay(struct sdhci_host *host, u8 value) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_sparx5_data *sdhci_sparx5 = sdhci_pltfm_priv(pltfm_host); + + pr_debug("%s: Set DLY_CC = %u\n", mmc_hostname(host->mmc), value); + + /* Update DLY_CC in HW */ + regmap_update_bits(sdhci_sparx5->cpu_ctrl, + CPU_REGS_GENERAL_CTRL, + MSHC_DLY_CC_MASK, + (value << MSHC_DLY_CC_SHIFT)); +} + +static void sdhci_sparx5_set_emmc(struct sdhci_host *host) +{ + if (!mmc_card_is_removable(host->mmc)) { + u8 value; + + value = sdhci_readb(host, MSHC2_EMMC_CTRL); + if (!(value & MSHC2_EMMC_CTRL_IS_EMMC)) { + value |= MSHC2_EMMC_CTRL_IS_EMMC; + pr_debug("%s: Set EMMC_CTRL: 0x%08x\n", + mmc_hostname(host->mmc), value); + sdhci_writeb(host, value, MSHC2_EMMC_CTRL); + } + } +} + +static void sdhci_sparx5_reset_emmc(struct sdhci_host *host) +{ + u8 value; + + pr_debug("%s: Toggle EMMC_CTRL.EMMC_RST_N\n", mmc_hostname(host->mmc)); + value = sdhci_readb(host, MSHC2_EMMC_CTRL) & + ~MSHC2_EMMC_CTRL_EMMC_RST_N; + sdhci_writeb(host, value, MSHC2_EMMC_CTRL); + /* For eMMC, minimum is 1us but give it 10us for good measure */ + usleep_range(10, 20); + sdhci_writeb(host, value | MSHC2_EMMC_CTRL_EMMC_RST_N, + MSHC2_EMMC_CTRL); + /* For eMMC, minimum is 200us but give it 300us for good measure */ + usleep_range(300, 400); +} + +static void sdhci_sparx5_reset(struct sdhci_host *host, u8 mask) +{ + pr_debug("%s: *** RESET: mask %d\n", mmc_hostname(host->mmc), mask); + + sdhci_reset(host, mask); + + /* Be sure CARD_IS_EMMC stays set */ + sdhci_sparx5_set_emmc(host); +} + +static const struct sdhci_ops sdhci_sparx5_ops = { + .set_clock = sdhci_set_clock, + .set_bus_width = sdhci_set_bus_width, + .set_uhs_signaling = sdhci_set_uhs_signaling, + .get_max_clock = sdhci_pltfm_clk_get_max_clock, + .reset = sdhci_sparx5_reset, + .adma_write_desc = sdhci_sparx5_adma_write_desc, +}; + +static const struct sdhci_pltfm_data sdhci_sparx5_pdata = { + .quirks = 0, + .quirks2 = SDHCI_QUIRK2_HOST_NO_CMD23 | /* Controller issue */ + SDHCI_QUIRK2_NO_1_8_V, /* No sdr104, ddr50, etc */ + .ops = &sdhci_sparx5_ops, +}; + +static int sdhci_sparx5_probe(struct platform_device *pdev) +{ + int ret; + const char *syscon = "microchip,sparx5-cpu-syscon"; + struct sdhci_host *host; + struct sdhci_pltfm_host *pltfm_host; + struct sdhci_sparx5_data *sdhci_sparx5; + struct device_node *np = pdev->dev.of_node; + u32 value; + u32 extra; + + host = sdhci_pltfm_init(pdev, &sdhci_sparx5_pdata, + sizeof(*sdhci_sparx5)); + + if (IS_ERR(host)) + return PTR_ERR(host); + + /* + * extra adma table cnt for cross 128M boundary handling. + */ + extra = DIV_ROUND_UP_ULL(dma_get_required_mask(&pdev->dev), SZ_128M); + if (extra > SDHCI_MAX_SEGS) + extra = SDHCI_MAX_SEGS; + host->adma_table_cnt += extra; + + pltfm_host = sdhci_priv(host); + sdhci_sparx5 = sdhci_pltfm_priv(pltfm_host); + sdhci_sparx5->host = host; + + pltfm_host->clk = devm_clk_get(&pdev->dev, "core"); + if (IS_ERR(pltfm_host->clk)) { + ret = PTR_ERR(pltfm_host->clk); + dev_err(&pdev->dev, "failed to get core clk: %d\n", ret); + goto free_pltfm; + } + ret = clk_prepare_enable(pltfm_host->clk); + if (ret) + goto free_pltfm; + + if (!of_property_read_u32(np, "microchip,clock-delay", &value) && + (value > 0 && value <= MSHC_DLY_CC_MAX)) + sdhci_sparx5->delay_clock = value; + + sdhci_get_of_property(pdev); + + ret = mmc_of_parse(host->mmc); + if (ret) + goto err_clk; + + sdhci_sparx5->cpu_ctrl = syscon_regmap_lookup_by_compatible(syscon); + if (IS_ERR(sdhci_sparx5->cpu_ctrl)) { + dev_err(&pdev->dev, "No CPU syscon regmap !\n"); + ret = PTR_ERR(sdhci_sparx5->cpu_ctrl); + goto err_clk; + } + + if (sdhci_sparx5->delay_clock >= 0) + sparx5_set_delay(host, sdhci_sparx5->delay_clock); + + if (!mmc_card_is_removable(host->mmc)) { + /* Do a HW reset of eMMC card */ + sdhci_sparx5_reset_emmc(host); + /* Update EMMC_CTRL */ + sdhci_sparx5_set_emmc(host); + /* If eMMC, disable SD and SDIO */ + host->mmc->caps2 |= (MMC_CAP2_NO_SDIO|MMC_CAP2_NO_SD); + } + + ret = sdhci_add_host(host); + if (ret) + goto err_clk; + + /* Set AXI bus master to use un-cached access (for DMA) */ + if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA) && + IS_ENABLED(CONFIG_DMA_DECLARE_COHERENT)) + sparx5_set_cacheable(host, ACP_CACHE_FORCE_ENA); + + pr_debug("%s: SDHC version: 0x%08x\n", + mmc_hostname(host->mmc), sdhci_readl(host, MSHC2_VERSION)); + pr_debug("%s: SDHC type: 0x%08x\n", + mmc_hostname(host->mmc), sdhci_readl(host, MSHC2_TYPE)); + + return ret; + +err_clk: + clk_disable_unprepare(pltfm_host->clk); +free_pltfm: + sdhci_pltfm_free(pdev); + return ret; +} + +static const struct of_device_id sdhci_sparx5_of_match[] = { + { .compatible = "microchip,dw-sparx5-sdhci" }, + { } +}; +MODULE_DEVICE_TABLE(of, sdhci_sparx5_of_match); + +static struct platform_driver sdhci_sparx5_driver = { + .driver = { + .name = "sdhci-sparx5", + .of_match_table = sdhci_sparx5_of_match, + .pm = &sdhci_pltfm_pmops, + }, + .probe = sdhci_sparx5_probe, + .remove = sdhci_pltfm_unregister, +}; + +module_platform_driver(sdhci_sparx5_driver); + +MODULE_DESCRIPTION("Sparx5 SDHCI OF driver"); +MODULE_AUTHOR("Lars Povlsen "); +MODULE_LICENSE("GPL v2"); From e449d983811211592dad6f5ef8b25d5549be5e8e Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Mon, 24 Aug 2020 09:02:36 +0800 Subject: [PATCH 19/91] mmc: sd: Use kobj_to_dev() instead of container_of() Use kobj_to_dev() instead of container_of() Signed-off-by: Tian Tao Link: https://lore.kernel.org/r/1598230956-58523-1-git-send-email-tiantao6@hisilicon.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/sd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 429ca14fa7e1..6f054c449d46 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -759,7 +759,7 @@ static struct attribute *sd_std_attrs[] = { static umode_t sd_std_is_visible(struct kobject *kobj, struct attribute *attr, int index) { - struct device *dev = container_of(kobj, struct device, kobj); + struct device *dev = kobj_to_dev(kobj); struct mmc_card *card = mmc_dev_to_card(dev); /* CIS vendor and device ids, revision and info string are available only for Combo cards */ From 9e70ff99ee871ec85e17da7c9d05cb5fcc306050 Mon Sep 17 00:00:00 2001 From: Haibo Chen Date: Mon, 24 Aug 2020 18:45:14 +0800 Subject: [PATCH 20/91] mmc: sdhci-esdhc-imx: remove unused code Value assigned to a variable(err) is never used, so remove it. Signed-off-by: Haibo Chen Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/1598265914-23606-1-git-send-email-haibo.chen@nxp.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-esdhc-imx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 0be334759c82..a2eb36c9b1da 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -1653,10 +1653,8 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) goto disable_ipg_clk; imx_data->pinctrl = devm_pinctrl_get(&pdev->dev); - if (IS_ERR(imx_data->pinctrl)) { - err = PTR_ERR(imx_data->pinctrl); + if (IS_ERR(imx_data->pinctrl)) dev_warn(mmc_dev(host->mmc), "could not get pinctrl\n"); - } if (esdhc_is_usdhc(imx_data)) { host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; From d425e42d600849ed81bca4e407a09f2555405ec7 Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Mon, 24 Aug 2020 18:18:50 +0100 Subject: [PATCH 21/91] mmc: sdhci-msm: enable compile-testing on !ARM There seems to be no particular reason to only test for ARM, so allow for build-testing on other platforms to increase coverage. Build-tested on x86 with allyesconfig. Signed-off-by: Alex Dewar Link: https://lore.kernel.org/r/20200824171854.406157-1-alex.dewar90@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 0ef1992ece3b..577b82dd13a0 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -537,7 +537,7 @@ config MMC_ATMELMCI config MMC_SDHCI_MSM tristate "Qualcomm SDHCI Controller Support" - depends on ARCH_QCOM || (ARM && COMPILE_TEST) + depends on ARCH_QCOM || COMPILE_TEST depends on MMC_SDHCI_PLTFM select MMC_SDHCI_IO_ACCESSORS select MMC_CQHCI From 7ca0f166f5b211f89fde9cf02357403e6f9715bc Mon Sep 17 00:00:00 2001 From: Faiz Abbas Date: Tue, 25 Aug 2020 22:30:15 +0530 Subject: [PATCH 22/91] mmc: sdhci_am654: Add workaround for card detect debounce timer There is a one time delay because of a card detect debounce timer in the controller IP. This timer runs as soon as power is applied to the module regardless of whether a card is present or not and any writes to SDHCI_POWER_ON will return 0 before it expires. This timeout has been measured to be about 1 second in am654x and j721e. Write-and-read-back in a loop on SDHCI_POWER_ON for a maximum of 1.5 seconds to make sure that the controller actually powers on. Signed-off-by: Faiz Abbas Link: https://lore.kernel.org/r/20200825170015.32285-1-faiz_abbas@ti.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci_am654.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index 0f3ed716d3d2..c5f47197d177 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -6,6 +6,7 @@ * */ #include +#include #include #include #include @@ -272,9 +273,19 @@ static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host, sdhci_set_clock(host, clock); } +static u8 sdhci_am654_write_power_on(struct sdhci_host *host, u8 val, int reg) +{ + writeb(val, host->ioaddr + reg); + usleep_range(1000, 10000); + return readb(host->ioaddr + reg); +} + +#define MAX_POWER_ON_TIMEOUT 1500000 /* us */ static void sdhci_am654_write_b(struct sdhci_host *host, u8 val, int reg) { unsigned char timing = host->mmc->ios.timing; + u8 pwr; + int ret; if (reg == SDHCI_HOST_CONTROL) { switch (timing) { @@ -291,6 +302,19 @@ static void sdhci_am654_write_b(struct sdhci_host *host, u8 val, int reg) } writeb(val, host->ioaddr + reg); + if (reg == SDHCI_POWER_CONTROL && (val & SDHCI_POWER_ON)) { + /* + * Power on will not happen until the card detect debounce + * timer expires. Wait at least 1.5 seconds for the power on + * bit to be set + */ + ret = read_poll_timeout(sdhci_am654_write_power_on, pwr, + pwr & SDHCI_POWER_ON, 0, + MAX_POWER_ON_TIMEOUT, false, host, val, + reg); + if (ret) + dev_warn(mmc_dev(host->mmc), "Power on failed\n"); + } } static int sdhci_am654_execute_tuning(struct mmc_host *mmc, u32 opcode) From 6e7d4de10890545b00f7d7c33310f1555963d592 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 20 Aug 2020 15:25:33 +0200 Subject: [PATCH 23/91] mmc: renesas_sdhi: move wrong 'hw_reset' to 'reset' This driver got the usage of 'hw_reset' wrong and missed that it is used to reset the remote HW (card) only, not the local one (controller). Move everything to the proper 'reset' callback. Also, add the generic reset code from TMIO, so we will ensure the same behaviour (it will get refactored away in a later patch). This also means we need to drop MMC_CAP_HW_RESET because this is currently not supported by our hardware. Signed-off-by: Wolfram Sang Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20200820132538.24758-2-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 904f5237d8f7..eced87845784 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -631,11 +631,20 @@ static bool renesas_sdhi_check_scc_error(struct tmio_mmc_host *host) return renesas_sdhi_manual_correction(host, use_4tap); } -static void renesas_sdhi_hw_reset(struct tmio_mmc_host *host) +static void renesas_sdhi_reset(struct tmio_mmc_host *host) { - struct renesas_sdhi *priv; + struct renesas_sdhi *priv = host_to_priv(host); - priv = host_to_priv(host); + /* FIXME - should we set stop clock reg here */ + sd_ctrl_write16(host, CTL_RESET_SD, 0x0000); + usleep_range(10000, 11000); + sd_ctrl_write16(host, CTL_RESET_SD, 0x0001); + usleep_range(10000, 11000); + + if (host->pdata->flags & TMIO_MMC_SDIO_IRQ) { + sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask); + sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001); + } renesas_sdhi_reset_scc(host, priv); renesas_sdhi_reset_hs400_mode(host, priv); @@ -862,11 +871,9 @@ int renesas_sdhi_probe(struct platform_device *pdev, renesas_sdhi_start_signal_voltage_switch; host->sdcard_irq_setbit_mask = TMIO_STAT_ALWAYS_SET_27; - /* SDR and HS200/400 registers requires HW reset */ if (of_data && of_data->scc_offset) { priv->scc_ctl = host->ctl + of_data->scc_offset; - host->mmc->caps |= MMC_CAP_HW_RESET; - host->hw_reset = renesas_sdhi_hw_reset; + host->reset = renesas_sdhi_reset; } } From 34e3211e5492756d4e59ef54f9ab1750ec7050ec Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 20 Aug 2020 15:25:34 +0200 Subject: [PATCH 24/91] Revert "mmc: tmio: fix reset operation" This reverts commit a87852c6b8827b7fece78ae57d871d56e4348e30. It did fix the issue, but was building on top of already wrong assumptions. The driver missed that 'hw_reset' was only for resetting remote HW (card) and not for the IP core. Since we fixed that in a previous patch, we can now remove this patch to make it clear that 'reset' is for resetting the IP core only. Also, cancelling DMA will only be called when actually needed again. It will also allow for further cleanups and better readability. Note that in addition to the revert, the call in 'tmio_mmc_execute_tuning' will be converted, too, to maintain the current behaviour. Signed-off-by: Wolfram Sang Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20200820132538.24758-3-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/tmio_mmc_core.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index 946fb013c610..125530e7bd17 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -178,18 +178,6 @@ static void tmio_mmc_reset(struct tmio_mmc_host *host) } } -static void tmio_mmc_hw_reset(struct mmc_host *mmc) -{ - struct tmio_mmc_host *host = mmc_priv(mmc); - - host->reset(host); - - tmio_mmc_abort_dma(host); - - if (host->hw_reset) - host->hw_reset(host); -} - static void tmio_mmc_reset_work(struct work_struct *work) { struct tmio_mmc_host *host = container_of(work, struct tmio_mmc_host, @@ -228,11 +216,12 @@ static void tmio_mmc_reset_work(struct work_struct *work) spin_unlock_irqrestore(&host->lock, flags); - tmio_mmc_hw_reset(host->mmc); + host->reset(host); /* Ready for new calls */ host->mrq = NULL; + tmio_mmc_abort_dma(host); mmc_request_done(host->mmc, mrq); } @@ -720,6 +709,14 @@ static int tmio_mmc_start_data(struct tmio_mmc_host *host, return 0; } +static void tmio_mmc_hw_reset(struct mmc_host *mmc) +{ + struct tmio_mmc_host *host = mmc_priv(mmc); + + if (host->hw_reset) + host->hw_reset(host); +} + static int tmio_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode) { struct tmio_mmc_host *host = mmc_priv(mmc); @@ -732,7 +729,7 @@ static int tmio_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode) if (ret < 0) { dev_warn(&host->pdev->dev, "Tuning procedure failed\n"); - tmio_mmc_hw_reset(mmc); + host->reset(host); } return ret; @@ -1180,7 +1177,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) _host->sdio_irq_mask = TMIO_SDIO_MASK_ALL; _host->set_clock(_host, 0); - tmio_mmc_hw_reset(mmc); + _host->reset(_host); _host->sdcard_irq_mask = sd_ctrl_read16_and_16_as_32(_host, CTL_IRQ_MASK); tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL); @@ -1283,7 +1280,7 @@ int tmio_mmc_host_runtime_resume(struct device *dev) struct tmio_mmc_host *host = dev_get_drvdata(dev); tmio_mmc_clk_enable(host); - tmio_mmc_hw_reset(host->mmc); + host->reset(host); if (host->clk_cache) host->set_clock(host, host->clk_cache); From a8c83064e73382d6bb069bd51c56074d1e4f4eec Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 20 Aug 2020 15:25:35 +0200 Subject: [PATCH 25/91] mmc: tmio: remove indirection of 'hw_reset' callback After Yamada-san's refactorization introducing 'tmio_mmc_host_alloc', we can populate mmc_ops directly and don't need a layer inbetween. Signed-off-by: Wolfram Sang Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20200820132538.24758-4-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/tmio_mmc.h | 1 - drivers/mmc/host/tmio_mmc_core.c | 9 --------- drivers/mmc/host/uniphier-sd.c | 5 +++-- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 0a4f36500add..dac717041c2d 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -178,7 +178,6 @@ struct tmio_mmc_host { unsigned int direction, int blk_size); int (*write16_hook)(struct tmio_mmc_host *host, int addr); void (*reset)(struct tmio_mmc_host *host); - void (*hw_reset)(struct tmio_mmc_host *host); bool (*check_retune)(struct tmio_mmc_host *host); /* diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index 125530e7bd17..a4bd0a0a305c 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -709,14 +709,6 @@ static int tmio_mmc_start_data(struct tmio_mmc_host *host, return 0; } -static void tmio_mmc_hw_reset(struct mmc_host *mmc) -{ - struct tmio_mmc_host *host = mmc_priv(mmc); - - if (host->hw_reset) - host->hw_reset(host); -} - static int tmio_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode) { struct tmio_mmc_host *host = mmc_priv(mmc); @@ -1008,7 +1000,6 @@ static struct mmc_host_ops tmio_mmc_ops = { .get_cd = tmio_mmc_get_cd, .enable_sdio_irq = tmio_mmc_enable_sdio_irq, .multi_io_quirk = tmio_multi_io_quirk, - .hw_reset = tmio_mmc_hw_reset, .execute_tuning = tmio_mmc_execute_tuning, }; diff --git a/drivers/mmc/host/uniphier-sd.c b/drivers/mmc/host/uniphier-sd.c index f82baf99fd69..55efd5c53249 100644 --- a/drivers/mmc/host/uniphier-sd.c +++ b/drivers/mmc/host/uniphier-sd.c @@ -409,8 +409,9 @@ static void uniphier_sd_clk_disable(struct tmio_mmc_host *host) clk_disable_unprepare(priv->clk); } -static void uniphier_sd_hw_reset(struct tmio_mmc_host *host) +static void uniphier_sd_hw_reset(struct mmc_host *mmc) { + struct tmio_mmc_host *host = mmc_priv(mmc); struct uniphier_sd_priv *priv = uniphier_sd_priv(host); reset_control_assert(priv->rst_hw); @@ -597,7 +598,7 @@ static int uniphier_sd_probe(struct platform_device *pdev) ret = PTR_ERR(priv->rst_hw); goto free_host; } - host->hw_reset = uniphier_sd_hw_reset; + host->ops.hw_reset = uniphier_sd_hw_reset; } if (host->mmc->caps & MMC_CAP_UHS) { From 576146ea4ed986f44a4406ec32a5d3363216b3d2 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 20 Aug 2020 15:25:36 +0200 Subject: [PATCH 26/91] mmc: tmio: factor out common parts of the reset routine Some TMIO variants need specific actions in their reset routine, but they are all based on a generic reset routine. So, the optional 'reset' callback will now only take care of the additional stuff and we will have a generic function around it. Less code, easier to maintain, and much more readable. Code in tmio_mmc.c is untested but in my TC6387XB datasheet the SDIO part is reset independently from the SD part, too. Signed-off-by: Wolfram Sang Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20200820132538.24758-5-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 11 ----------- drivers/mmc/host/tmio_mmc.c | 8 -------- drivers/mmc/host/tmio_mmc_core.c | 14 +++++++------- 3 files changed, 7 insertions(+), 26 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index eced87845784..9b2d4e8039d9 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -635,17 +635,6 @@ static void renesas_sdhi_reset(struct tmio_mmc_host *host) { struct renesas_sdhi *priv = host_to_priv(host); - /* FIXME - should we set stop clock reg here */ - sd_ctrl_write16(host, CTL_RESET_SD, 0x0000); - usleep_range(10000, 11000); - sd_ctrl_write16(host, CTL_RESET_SD, 0x0001); - usleep_range(10000, 11000); - - if (host->pdata->flags & TMIO_MMC_SDIO_IRQ) { - sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask); - sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001); - } - renesas_sdhi_reset_scc(host, priv); renesas_sdhi_reset_hs400_mode(host, priv); diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 93e83ad25976..757c90160ae4 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -77,18 +77,10 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, static void tmio_mmc_reset(struct tmio_mmc_host *host) { - /* FIXME - should we set stop clock reg here */ - sd_ctrl_write16(host, CTL_RESET_SD, 0x0000); sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0000); usleep_range(10000, 11000); - sd_ctrl_write16(host, CTL_RESET_SD, 0x0001); sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0001); usleep_range(10000, 11000); - - if (host->pdata->flags & TMIO_MMC_SDIO_IRQ) { - sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask); - sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001); - } } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index a4bd0a0a305c..f68c10b8ed61 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -172,6 +172,9 @@ static void tmio_mmc_reset(struct tmio_mmc_host *host) sd_ctrl_write16(host, CTL_RESET_SD, 0x0001); usleep_range(10000, 11000); + if (host->reset) + host->reset(host); + if (host->pdata->flags & TMIO_MMC_SDIO_IRQ) { sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask); sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001); @@ -216,7 +219,7 @@ static void tmio_mmc_reset_work(struct work_struct *work) spin_unlock_irqrestore(&host->lock, flags); - host->reset(host); + tmio_mmc_reset(host); /* Ready for new calls */ host->mrq = NULL; @@ -721,7 +724,7 @@ static int tmio_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode) if (ret < 0) { dev_warn(&host->pdev->dev, "Tuning procedure failed\n"); - host->reset(host); + tmio_mmc_reset(host); } return ret; @@ -1144,9 +1147,6 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) mmc->caps & MMC_CAP_NEEDS_POLL || !mmc_card_is_removable(mmc)); - if (!_host->reset) - _host->reset = tmio_mmc_reset; - /* * On Gen2+, eMMC with NONREMOVABLE currently fails because native * hotplug gets disabled. It seems RuntimePM related yet we need further @@ -1168,7 +1168,7 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) _host->sdio_irq_mask = TMIO_SDIO_MASK_ALL; _host->set_clock(_host, 0); - _host->reset(_host); + tmio_mmc_reset(_host); _host->sdcard_irq_mask = sd_ctrl_read16_and_16_as_32(_host, CTL_IRQ_MASK); tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL); @@ -1271,7 +1271,7 @@ int tmio_mmc_host_runtime_resume(struct device *dev) struct tmio_mmc_host *host = dev_get_drvdata(dev); tmio_mmc_clk_enable(host); - host->reset(host); + tmio_mmc_reset(host); if (host->clk_cache) host->set_clock(host, host->clk_cache); From 5b0739d76227fd5a3f02f014385bfa9c86e0404b Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 20 Aug 2020 15:25:37 +0200 Subject: [PATCH 27/91] mmc: tmio: don't reset whole IP core when tuning fails SDHI needs to reset the SCC only, not the whole IP core. So, if tuning fails, don't handle specifics in the generic TMIO core, but in the specific drivers. For SDHI, we need to move around the reset routine a bit. It is not modified. Signed-off-by: Wolfram Sang Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20200820132538.24758-6-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 45 +++++++++++++++------------- drivers/mmc/host/tmio_mmc_core.c | 4 +-- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 9b2d4e8039d9..50a92d49efd9 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -432,6 +432,25 @@ static int renesas_sdhi_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_io return 0; } +static void renesas_sdhi_reset(struct tmio_mmc_host *host) +{ + struct renesas_sdhi *priv = host_to_priv(host); + + renesas_sdhi_reset_scc(host, priv); + renesas_sdhi_reset_hs400_mode(host, priv); + + sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN | + sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); + + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL, + ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN & + sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL)); + + if (host->pdata->flags & TMIO_MMC_MIN_RCAR2) + sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, + TMIO_MASK_INIT_RCAR2); +} + #define SH_MOBILE_SDHI_MIN_TAP_ROW 3 static int renesas_sdhi_select_tuning(struct tmio_mmc_host *host) @@ -503,7 +522,7 @@ static int renesas_sdhi_select_tuning(struct tmio_mmc_host *host) static int renesas_sdhi_execute_tuning(struct tmio_mmc_host *host, u32 opcode) { struct renesas_sdhi *priv = host_to_priv(host); - int i; + int i, ret; priv->tap_num = renesas_sdhi_init_tuning(host); if (!priv->tap_num) @@ -531,7 +550,10 @@ static int renesas_sdhi_execute_tuning(struct tmio_mmc_host *host, u32 opcode) set_bit(i, priv->smpcmp); } - return renesas_sdhi_select_tuning(host); + ret = renesas_sdhi_select_tuning(host); + if (ret < 0) + renesas_sdhi_reset(host); + return ret; } static bool renesas_sdhi_manual_correction(struct tmio_mmc_host *host, bool use_4tap) @@ -631,25 +653,6 @@ static bool renesas_sdhi_check_scc_error(struct tmio_mmc_host *host) return renesas_sdhi_manual_correction(host, use_4tap); } -static void renesas_sdhi_reset(struct tmio_mmc_host *host) -{ - struct renesas_sdhi *priv = host_to_priv(host); - - renesas_sdhi_reset_scc(host, priv); - renesas_sdhi_reset_hs400_mode(host, priv); - - sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN | - sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); - - sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL, - ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN & - sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL)); - - if (host->pdata->flags & TMIO_MMC_MIN_RCAR2) - sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, - TMIO_MASK_INIT_RCAR2); -} - static int renesas_sdhi_wait_idle(struct tmio_mmc_host *host, u32 bit) { int timeout = 1000; diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index f68c10b8ed61..e7bad761c714 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -722,10 +722,8 @@ static int tmio_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode) ret = host->execute_tuning(host, opcode); - if (ret < 0) { + if (ret < 0) dev_warn(&host->pdev->dev, "Tuning procedure failed\n"); - tmio_mmc_reset(host); - } return ret; } From 510bfe58936f7d79d4c377bcc7425244d879b1ff Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 20 Aug 2020 15:25:38 +0200 Subject: [PATCH 28/91] mmc: tmio: remove indirection of 'execute_tuning' callback After all the previous refactorization, we can now populate mmc_ops directly and don't need a layer inbetween. The NULL-pointer check and the error printout are already done by the MMC core. Signed-off-by: Wolfram Sang Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20200820132538.24758-7-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 7 ++++--- drivers/mmc/host/tmio_mmc.h | 6 ------ drivers/mmc/host/tmio_mmc_core.c | 17 ----------------- 3 files changed, 4 insertions(+), 26 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 50a92d49efd9..1243c42d3d1b 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -519,8 +519,9 @@ static int renesas_sdhi_select_tuning(struct tmio_mmc_host *host) return 0; } -static int renesas_sdhi_execute_tuning(struct tmio_mmc_host *host, u32 opcode) +static int renesas_sdhi_execute_tuning(struct mmc_host *mmc, u32 opcode) { + struct tmio_mmc_host *host = mmc_priv(mmc); struct renesas_sdhi *priv = host_to_priv(host); int i, ret; @@ -543,7 +544,7 @@ static int renesas_sdhi_execute_tuning(struct tmio_mmc_host *host, u32 opcode) /* Set sampling clock position */ sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TAPSET, i % priv->tap_num); - if (mmc_send_tuning(host->mmc, opcode, NULL) == 0) + if (mmc_send_tuning(mmc, opcode, NULL) == 0) set_bit(i, priv->taps); if (sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_SMPCMP) == 0) @@ -942,8 +943,8 @@ int renesas_sdhi_probe(struct platform_device *pdev, if (!hit) dev_warn(&host->pdev->dev, "Unknown clock rate for tuning\n"); - host->execute_tuning = renesas_sdhi_execute_tuning; host->check_retune = renesas_sdhi_check_scc_error; + host->ops.execute_tuning = renesas_sdhi_execute_tuning; host->ops.prepare_hs400_tuning = renesas_sdhi_prepare_hs400_tuning; host->ops.hs400_downgrade = renesas_sdhi_disable_scc; host->ops.hs400_complete = renesas_sdhi_hs400_complete; diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index dac717041c2d..51b5f388f6d8 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -180,12 +180,6 @@ struct tmio_mmc_host { void (*reset)(struct tmio_mmc_host *host); bool (*check_retune)(struct tmio_mmc_host *host); - /* - * Mandatory callback for tuning to occur which is optional for SDR50 - * and mandatory for SDR104. - */ - int (*execute_tuning)(struct tmio_mmc_host *host, u32 opcode); - void (*prepare_hs400_tuning)(struct tmio_mmc_host *host); void (*hs400_downgrade)(struct tmio_mmc_host *host); void (*hs400_complete)(struct tmio_mmc_host *host); diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index e7bad761c714..0f266cbf82b8 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -712,22 +712,6 @@ static int tmio_mmc_start_data(struct tmio_mmc_host *host, return 0; } -static int tmio_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode) -{ - struct tmio_mmc_host *host = mmc_priv(mmc); - int ret; - - if (!host->execute_tuning) - return 0; - - ret = host->execute_tuning(host, opcode); - - if (ret < 0) - dev_warn(&host->pdev->dev, "Tuning procedure failed\n"); - - return ret; -} - static void tmio_process_mrq(struct tmio_mmc_host *host, struct mmc_request *mrq) { @@ -1001,7 +985,6 @@ static struct mmc_host_ops tmio_mmc_ops = { .get_cd = tmio_mmc_get_cd, .enable_sdio_irq = tmio_mmc_enable_sdio_irq, .multi_io_quirk = tmio_multi_io_quirk, - .execute_tuning = tmio_mmc_execute_tuning, }; static int tmio_mmc_init_ocr(struct tmio_mmc_host *host) From 4dac686bb3571b65b58316991eb833431a3d19f1 Mon Sep 17 00:00:00 2001 From: Veerabhadrarao Badiganti Date: Thu, 27 Aug 2020 20:51:28 +0530 Subject: [PATCH 29/91] mmc: sdhci-msm: Enable restore_dll_config flag for sc7180 target On sc7180 target, issues are observed with HS400 mode due to a hardware limitation. If sdcc clock is dynamically gated and ungated, the very next command is failing with command CRC/timeout errors. To mitigate this issue, DLL phase has to be restored whenever sdcc clock is gated dynamically. The restore_dll_config ensures this. Enabling this flag with this change. And simply re-using the sdm845 target configuration for this flag. Signed-off-by: Veerabhadrarao Badiganti Reviewed-by: Douglas Anderson Tested-by: Douglas Anderson Link: https://lore.kernel.org/r/1598541694-15694-1-git-send-email-vbadigan@codeaurora.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-msm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 5a33389037cd..d4c02884cca8 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -2151,6 +2151,7 @@ static const struct of_device_id sdhci_msm_dt_match[] = { {.compatible = "qcom,sdhci-msm-v5", .data = &sdhci_msm_v5_var}, {.compatible = "qcom,sdm845-sdhci", .data = &sdm845_sdhci_var}, {.compatible = "qcom,sm8250-sdhci", .data = &sm8250_sdhci_var}, + {.compatible = "qcom,sc7180-sdhci", .data = &sdm845_sdhci_var}, {}, }; From 887ba410ede62da12e77684072f6c7491c0fa909 Mon Sep 17 00:00:00 2001 From: Chun-Hung Wu Date: Thu, 27 Aug 2020 17:33:02 +0800 Subject: [PATCH 30/91] mmc: cqhci: add new cqhci_host_ops pre_enable() and post_disable() Add pre_enable() and post_disable() for cqhci_host_ops. Add hook functions before cqhci enable and after cqhci disable for platforms need them. Signed-off-by: Chun-Hung Wu Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/1598520783-25250-2-git-send-email-chun-hung.wu@mediatek.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/cqhci.c | 6 ++++++ drivers/mmc/host/cqhci.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/drivers/mmc/host/cqhci.c b/drivers/mmc/host/cqhci.c index cfa87dfa73d8..697fe40756bf 100644 --- a/drivers/mmc/host/cqhci.c +++ b/drivers/mmc/host/cqhci.c @@ -376,6 +376,9 @@ static void cqhci_off(struct mmc_host *mmc) else pr_debug("%s: cqhci: CQE off\n", mmc_hostname(mmc)); + if (cq_host->ops->post_disable) + cq_host->ops->post_disable(mmc); + mmc->cqe_on = false; } @@ -580,6 +583,9 @@ static int cqhci_request(struct mmc_host *mmc, struct mmc_request *mrq) __cqhci_enable(cq_host); if (!mmc->cqe_on) { + if (cq_host->ops->pre_enable) + cq_host->ops->pre_enable(mmc); + cqhci_writel(cq_host, 0, CQHCI_CTL); mmc->cqe_on = true; pr_debug("%s: cqhci: CQE on\n", mmc_hostname(mmc)); diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h index 437700179de4..89bf6adbce8c 100644 --- a/drivers/mmc/host/cqhci.h +++ b/drivers/mmc/host/cqhci.h @@ -206,6 +206,8 @@ struct cqhci_host_ops { void (*disable)(struct mmc_host *mmc, bool recovery); void (*update_dcmd_desc)(struct mmc_host *mmc, struct mmc_request *mrq, u64 *data); + void (*pre_enable)(struct mmc_host *mmc); + void (*post_disable)(struct mmc_host *mmc); }; static inline void cqhci_writel(struct cqhci_host *host, u32 val, int reg) From e282f2045a3df69e8303488684bc9f3a23d2677d Mon Sep 17 00:00:00 2001 From: Chun-Hung Wu Date: Thu, 27 Aug 2020 17:33:03 +0800 Subject: [PATCH 31/91] mmc: mediatek: add pre_enable() and post_disable() hook function CQHCI_ENABLE bit in CQHCI_CFG should be disabled after msdc_cqe_disable(), and should be enabled before msdc_ceq_enable() for MTK platform. Add hook functions for cqhci_host_ops->pre_enable() and cqhci_host_ops->post_disable(). Signed-off-by: Chun-Hung Wu Acked-by: Adrian Hunter Link: https://lore.kernel.org/r/1598520783-25250-3-git-send-email-chun-hung.wu@mediatek.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/mtk-sd.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index b0c27944db7f..ed2b24691b4f 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -2290,6 +2290,26 @@ static void msdc_cqe_disable(struct mmc_host *mmc, bool recovery) } } +static void msdc_cqe_pre_enable(struct mmc_host *mmc) +{ + struct cqhci_host *cq_host = mmc->cqe_private; + u32 reg; + + reg = cqhci_readl(cq_host, CQHCI_CFG); + reg |= CQHCI_ENABLE; + cqhci_writel(cq_host, reg, CQHCI_CFG); +} + +static void msdc_cqe_post_disable(struct mmc_host *mmc) +{ + struct cqhci_host *cq_host = mmc->cqe_private; + u32 reg; + + reg = cqhci_readl(cq_host, CQHCI_CFG); + reg &= ~CQHCI_ENABLE; + cqhci_writel(cq_host, reg, CQHCI_CFG); +} + static const struct mmc_host_ops mt_msdc_ops = { .post_req = msdc_post_req, .pre_req = msdc_pre_req, @@ -2309,6 +2329,8 @@ static const struct mmc_host_ops mt_msdc_ops = { static const struct cqhci_host_ops msdc_cmdq_ops = { .enable = msdc_cqe_enable, .disable = msdc_cqe_disable, + .pre_enable = msdc_cqe_pre_enable, + .post_disable = msdc_cqe_post_disable, }; static void msdc_of_property_parse(struct platform_device *pdev, From 8d62fa831fd2a3a58726f731726f30fc425d7f55 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Fri, 28 Aug 2020 23:47:14 +0200 Subject: [PATCH 32/91] mmc: sdhci-iproc: Enable eMMC DDR 3.3V support for bcm2711 The emmc2 interface on the bcm2711 supports DDR modes for eMMC devices running at 3.3V. This allows to run eMMC module with 3.3V signaling voltage at DDR52 mode on the Raspberry Pi 4 using a SD adapter: clock: 52000000 Hz actual clock: 50000000 Hz vdd: 21 (3.3 ~ 3.4 V) bus mode: 2 (push-pull) chip select: 0 (don't care) power mode: 2 (on) bus width: 2 (4 bits) timing spec: 8 (mmc DDR52) signal voltage: 0 (3.30 V) driver type: 0 (driver type B) Link: https://github.com/raspberrypi/linux/issues/3802 Signed-off-by: Stefan Wahren Link: https://lore.kernel.org/r/1598651234-29826-1-git-send-email-stefan.wahren@i2se.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-iproc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c index e2d8dfe90077..b540aa6faacb 100644 --- a/drivers/mmc/host/sdhci-iproc.c +++ b/drivers/mmc/host/sdhci-iproc.c @@ -283,6 +283,7 @@ static const struct sdhci_pltfm_data sdhci_bcm2711_pltfm_data = { static const struct sdhci_iproc_data bcm2711_data = { .pdata = &sdhci_bcm2711_pltfm_data, + .mmc_caps = MMC_CAP_3_3V_DDR, }; static const struct of_device_id sdhci_iproc_of_match[] = { From 80fd350b9590d567196de215391141880cc8ea5a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sat, 29 Aug 2020 08:25:05 +0200 Subject: [PATCH 33/91] dt-bindings: mmc: fsl-imx-esdhc: Fix i.MX 8 compatible matching The i.MX 8 DTSes use two compatibles so update the binding to fix dtbs_check warnings like: arch/arm64/boot/dts/freescale/imx8mn-evk.dt.yaml: mmc@30b40000: compatible: ['fsl,imx8mn-usdhc', 'fsl,imx7d-usdhc'] is too long From schema: Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml arch/arm64/boot/dts/freescale/imx8mn-evk.dt.yaml: mmc@30b40000: compatible: Additional items are not allowed ('fsl,imx7d-usdhc' was unexpected) arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dt.yaml: mmc@30b40000: compatible: ['fsl,imx8mn-usdhc', 'fsl,imx7d-usdhc'] is too long Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200829062505.4642-1-krzk@kernel.org Signed-off-by: Ulf Hansson --- .../bindings/clock/imx8qxp-lpcg.yaml | 2 +- .../bindings/mmc/fsl-imx-esdhc.yaml | 37 ++++++++++--------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.yaml b/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.yaml index 1d5e9bcce4c8..33f3010f48c3 100644 --- a/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.yaml +++ b/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.yaml @@ -62,7 +62,7 @@ examples: }; mmc@5b010000 { - compatible = "fsl,imx8qxp-usdhc"; + compatible = "fsl,imx8qxp-usdhc", "fsl,imx7d-usdhc"; interrupts = ; reg = <0x5b010000 0x10000>; clocks = <&conn_lpcg IMX_CONN_LPCG_SDHC0_IPG_CLK>, diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml index 10b45966f1b8..e71d13c2d109 100644 --- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml @@ -21,23 +21,26 @@ description: | properties: compatible: - enum: - - fsl,imx25-esdhc - - fsl,imx35-esdhc - - fsl,imx51-esdhc - - fsl,imx53-esdhc - - fsl,imx6q-usdhc - - fsl,imx6sl-usdhc - - fsl,imx6sx-usdhc - - fsl,imx6ull-usdhc - - fsl,imx7d-usdhc - - fsl,imx7ulp-usdhc - - fsl,imx8mq-usdhc - - fsl,imx8mm-usdhc - - fsl,imx8mn-usdhc - - fsl,imx8mp-usdhc - - fsl,imx8qm-usdhc - - fsl,imx8qxp-usdhc + oneOf: + - enum: + - fsl,imx25-esdhc + - fsl,imx35-esdhc + - fsl,imx51-esdhc + - fsl,imx53-esdhc + - fsl,imx6q-usdhc + - fsl,imx6sl-usdhc + - fsl,imx6sx-usdhc + - fsl,imx6ull-usdhc + - fsl,imx7d-usdhc + - fsl,imx7ulp-usdhc + - items: + - enum: + - fsl,imx8mm-usdhc + - fsl,imx8mn-usdhc + - fsl,imx8mp-usdhc + - fsl,imx8mq-usdhc + - fsl,imx8qxp-usdhc + - const: fsl,imx7d-usdhc reg: maxItems: 1 From 9381118fcfd7794dee7e2a8fd1bbbbc3ecb9c240 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 31 Aug 2020 18:11:47 +0200 Subject: [PATCH 34/91] dt-bindings: mmc: mmc-pwreq-simple: Accept more than one reset GPIO There might be multiple reset GPIOs but dtschema has trouble parsing it if there are no maxItems: arch/arm/boot/dts/exynos5250-snow.dt.yaml: mmc3_pwrseq: reset-gpios: [[20, 2, 1], [20, 1, 1]] is too long From schema: Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.yaml Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200831161147.13515-2-krzk@kernel.org Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.yaml b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.yaml index 449215444723..8d625f903856 100644 --- a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.yaml +++ b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.yaml @@ -20,6 +20,8 @@ properties: reset-gpios: minItems: 1 + # Put some limit to avoid false warnings + maxItems: 32 description: contains a list of GPIO specifiers. The reset GPIOs are asserted at initialization and prior we start the power up procedure of the card. From e0c29be62cdc32605281024a662b2f8f690a3f77 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 31 Aug 2020 12:23:24 +0200 Subject: [PATCH 35/91] mmc: meson-gx: use wrapper to avoid accessing internal vars Signed-off-by: Wolfram Sang Reviewed-by: Kevin Hilman Link: https://lore.kernel.org/r/20200831102324.12566-1-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/meson-gx-mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index 08a3b1c05acb..a1db8685e30e 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -521,7 +521,7 @@ static int meson_mmc_resampling_tuning(struct mmc_host *mmc, u32 opcode) val |= ADJUST_ADJ_EN; writel(val, host->regs + host->data->adjust); - if (mmc->doing_retune) + if (mmc_doing_retune(mmc)) dly = FIELD_GET(ADJUST_ADJ_DELAY_MASK, val) + 1; else dly = 0; From 1796164fac7e348f74a0f1f1cae995b22d002315 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 1 Sep 2020 10:50:03 +0200 Subject: [PATCH 36/91] dt-bindings: mmc: document alias support As for I2C and SPI, it now is possible to reserve a fixed index for mmc/mmcblk devices. Signed-off-by: Matthias Schiffer Link: https://lore.kernel.org/r/20200901085004.2512-1-matthias.schiffer@ew.tq-group.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/mmc-controller.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml index b96da0c7f819..f928f66fc59a 100644 --- a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml +++ b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml @@ -14,6 +14,10 @@ description: | that requires the respective functionality should implement them using these definitions. + It is possible to assign a fixed index mmcN to an MMC host controller + (and the corresponding mmcblkN devices) by defining an alias in the + /aliases device tree node. + properties: $nodename: pattern: "^mmc(@.*)?$" From fa2d0aa96941e8dc347e49a04c75468e3002ee20 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 1 Sep 2020 10:50:04 +0200 Subject: [PATCH 37/91] mmc: core: Allow setting slot index via device tree alias As with GPIO, UART and others, allow specifying the device index via the aliases node in the device tree. On embedded devices, there is often a combination of removable (e.g. SD card) and non-removable MMC devices (e.g. eMMC). Therefore the index might change depending on * host of removable device * removable card present or not This makes it difficult to hardcode the root device, if it is on the non-removable device. E.g. if SD card is present eMMC will be mmcblk1, if SD card is not present at boot, eMMC will be mmcblk0. Alternative solutions like PARTUUIDs do not cover the case where multiple mmcblk devices contain the same image. This is a common issue on devices that can boot both from eMMC (for regular boot) and SD cards (as a temporary boot medium for development). When a firmware image is installed to eMMC after a test boot via SD card, there will be no reliable way to refer to a specific device using (PART)UUIDs oder LABELs. The demand for this feature has led to multiple attempts to implement it, dating back at least to 2012 (see https://www.spinics.net/lists/linux-mmc/msg26586.html for a previous discussion from 2014). All indices defined in the aliases node will be reserved for use by the respective MMC device, moving the indices of devices that don't have an alias up into the non-reserved range. If the aliases node is not found, the driver will act as before. This is a rebased and cleaned up version of https://www.spinics.net/lists/linux-mmc/msg26588.html . Based-on-patch-by: Sascha Hauer Link: https://lkml.org/lkml/2020/8/5/194 Signed-off-by: Matthias Schiffer Link: https://lore.kernel.org/r/20200901085004.2512-2-matthias.schiffer@ew.tq-group.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/host.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index c8fae6611b73..96b2ca1f1b06 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -376,6 +376,20 @@ int mmc_of_parse_voltage(struct device_node *np, u32 *mask) } EXPORT_SYMBOL(mmc_of_parse_voltage); +/** + * mmc_first_nonreserved_index() - get the first index that is not reserved + */ +static int mmc_first_nonreserved_index(void) +{ + int max; + + max = of_alias_get_highest_id("mmc"); + if (max < 0) + return 0; + + return max + 1; +} + /** * mmc_alloc_host - initialise the per-host structure. * @extra: sizeof private data structure @@ -387,6 +401,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) { int err; struct mmc_host *host; + int alias_id, min_idx, max_idx; host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); if (!host) @@ -395,7 +410,16 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) /* scanning will be enabled when we're ready */ host->rescan_disable = 1; - err = ida_simple_get(&mmc_host_ida, 0, 0, GFP_KERNEL); + alias_id = of_alias_get_id(dev->of_node, "mmc"); + if (alias_id >= 0) { + min_idx = alias_id; + max_idx = alias_id + 1; + } else { + min_idx = mmc_first_nonreserved_index(); + max_idx = 0; + } + + err = ida_simple_get(&mmc_host_ida, min_idx, max_idx, GFP_KERNEL); if (err < 0) { kfree(host); return NULL; From aec429e09e2d51e34ecdea5446d6061ec2e4bf74 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 2 Sep 2020 21:36:48 +0200 Subject: [PATCH 38/91] mmc: bcm2835: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and the error value gets printed. Signed-off-by: Krzysztof Kozlowski Acked-by: Florian Fainelli Link: https://lore.kernel.org/r/20200902193658.20539-2-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/bcm2835.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c index a0767790a826..35320bc9dc02 100644 --- a/drivers/mmc/host/bcm2835.c +++ b/drivers/mmc/host/bcm2835.c @@ -1406,9 +1406,7 @@ static int bcm2835_probe(struct platform_device *pdev) clk = devm_clk_get(dev, NULL); if (IS_ERR(clk)) { - ret = PTR_ERR(clk); - if (ret != -EPROBE_DEFER) - dev_err(dev, "could not get clk: %d\n", ret); + ret = dev_err_probe(dev, PTR_ERR(clk), "could not get clk\n"); goto err; } From 3a35e7e1bd50f794ede9ed1291402bacf2c79480 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 2 Sep 2020 21:36:49 +0200 Subject: [PATCH 39/91] mmc: davinci: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and the error value gets printed. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200902193658.20539-3-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/davinci_mmc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index e50a08bce7ef..fad1010fb52b 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c @@ -1240,9 +1240,8 @@ static int davinci_mmcsd_probe(struct platform_device *pdev) pdev->id_entry = match->data; ret = mmc_of_parse(mmc); if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, - "could not parse of data: %d\n", ret); + dev_err_probe(&pdev->dev, ret, + "could not parse of data\n"); goto parse_fail; } } else { From 380a99a2d084d78d6dd47f63f3a178e24321c681 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 2 Sep 2020 21:36:50 +0200 Subject: [PATCH 40/91] mmc: dw_mmc-zx: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and the error value gets printed. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200902193658.20539-4-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc-zx.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/host/dw_mmc-zx.c b/drivers/mmc/host/dw_mmc-zx.c index eada648b27ec..d9e483432a61 100644 --- a/drivers/mmc/host/dw_mmc-zx.c +++ b/drivers/mmc/host/dw_mmc-zx.c @@ -155,7 +155,6 @@ static int dw_mci_zx_parse_dt(struct dw_mci *host) struct device_node *node; struct dw_mci_zx_priv_data *priv; struct regmap *sysc_base; - int ret; /* syscon is needed only by emmc */ node = of_parse_phandle(np, "zte,aon-syscon", 0); @@ -163,13 +162,9 @@ static int dw_mci_zx_parse_dt(struct dw_mci *host) sysc_base = syscon_node_to_regmap(node); of_node_put(node); - if (IS_ERR(sysc_base)) { - ret = PTR_ERR(sysc_base); - if (ret != -EPROBE_DEFER) - dev_err(host->dev, "Can't get syscon: %d\n", - ret); - return ret; - } + if (IS_ERR(sysc_base)) + return dev_err_probe(host->dev, PTR_ERR(sysc_base), + "Can't get syscon\n"); } else { return 0; } From 295208a6666de8c438054c625d97138a05087655 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 2 Sep 2020 21:36:51 +0200 Subject: [PATCH 41/91] mmc: jz4740: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and the error value gets printed. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200902193658.20539-5-krzk@kernel.org Reviewed-by: Paul Cercueil Signed-off-by: Ulf Hansson --- drivers/mmc/host/jz4740_mmc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index 81d71010b474..fea0a42010c7 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -991,9 +991,7 @@ static int jz4740_mmc_probe(struct platform_device* pdev) ret = mmc_of_parse(mmc); if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, - "could not parse device properties: %d\n", ret); + dev_err_probe(&pdev->dev, ret, "could not parse device properties\n"); goto err_free_host; } From 89280d0963fdb615f8fdfc96592f9aab27592c14 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 2 Sep 2020 21:36:52 +0200 Subject: [PATCH 42/91] mmc: meson: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and the error value gets printed. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200902193658.20539-6-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/meson-gx-mmc.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index a1db8685e30e..a68b43082f61 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -426,11 +426,9 @@ static int meson_mmc_clk_init(struct meson_host *host) snprintf(name, sizeof(name), "clkin%d", i); clk = devm_clk_get(host->dev, name); - if (IS_ERR(clk)) { - if (clk != ERR_PTR(-EPROBE_DEFER)) - dev_err(host->dev, "Missing clock %s\n", name); - return PTR_ERR(clk); - } + if (IS_ERR(clk)) + return dev_err_probe(host->dev, PTR_ERR(clk), + "Missing clock %s\n", name); mux_parent_names[i] = __clk_get_name(clk); } @@ -1077,12 +1075,8 @@ static int meson_mmc_probe(struct platform_device *pdev) } ret = device_reset_optional(&pdev->dev); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "device reset failed: %d\n", ret); - - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "device reset failed\n"); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); host->regs = devm_ioremap_resource(&pdev->dev, res); From 72ea817db5d26e2dab3695a576b5557ada9cd722 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 2 Sep 2020 21:36:54 +0200 Subject: [PATCH 43/91] mmc: sdhci-of-arasan: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and the error value gets printed. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200902193658.20539-8-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-arasan.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index f186fbd016b1..3aea46db2ea7 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -1543,10 +1543,9 @@ static int sdhci_arasan_probe(struct platform_device *pdev) of_node_put(node); if (IS_ERR(sdhci_arasan->soc_ctl_base)) { - ret = PTR_ERR(sdhci_arasan->soc_ctl_base); - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "Can't get syscon: %d\n", - ret); + ret = dev_err_probe(&pdev->dev, + PTR_ERR(sdhci_arasan->soc_ctl_base), + "Can't get syscon\n"); goto err_pltfm_free; } } From 180a46652e09c7882330ab9ace060f0e13ca13f0 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 2 Sep 2020 21:36:55 +0200 Subject: [PATCH 44/91] mmc: sdhci-tegra: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code and the error value gets printed. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200902193658.20539-9-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-tegra.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 13fbf70b5fde..428cdc53c858 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -1660,11 +1660,8 @@ static int sdhci_tegra_probe(struct platform_device *pdev) clk = devm_clk_get(mmc_dev(host->mmc), NULL); if (IS_ERR(clk)) { - rc = PTR_ERR(clk); - - if (rc != -EPROBE_DEFER) - dev_err(&pdev->dev, "failed to get clock: %d\n", rc); - + rc = dev_err_probe(&pdev->dev, PTR_ERR(clk), + "failed to get clock\n"); goto err_clk_get; } clk_prepare_enable(clk); From 308d2722f6430839f06572af776f37f7af697134 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 2 Sep 2020 21:36:56 +0200 Subject: [PATCH 45/91] mmc: dw_mmc: Simplify with dev_err_probe() Common pattern of handling deferred probe can be simplified with dev_err_probe(). Less code, the error value gets printed and real error from dw_mci_parse_dt() is passed further instead of fixed -EINVAL. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200902193658.20539-10-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 0fba940544ca..43c5795691fb 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -3161,12 +3161,9 @@ int dw_mci_probe(struct dw_mci *host) if (!host->pdata) { host->pdata = dw_mci_parse_dt(host); - if (PTR_ERR(host->pdata) == -EPROBE_DEFER) { - return -EPROBE_DEFER; - } else if (IS_ERR(host->pdata)) { - dev_err(host->dev, "platform data not available\n"); - return -EINVAL; - } + if (IS_ERR(host->pdata)) + return dev_err_probe(host->dev, PTR_ERR(host->pdata), + "platform data not available\n"); } host->biu_clk = devm_clk_get(host->dev, "biu"); From b5f9a2c686d91ad5a97ee4a5be9ae1e6da8d4789 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 2 Sep 2020 21:36:57 +0200 Subject: [PATCH 46/91] mmc: sdhci-of-sparx5: Use proper printk format for dma_addr_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dma_addr_t size varies between architectures so use dedicated printk format to fix compile testing warning (e.g. on 32-bit MIPS): drivers/mmc/host/sdhci-of-sparx5.c:63:11: warning: format ‘%llx’ expects argument of type ‘long long unsigned int’, but argument 5 has type ‘dma_addr_t {aka unsigned int}’ [-Wformat=] Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200902193658.20539-11-krzk@kernel.org Acked-by: Lars Povlsen Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-sparx5.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-sparx5.c b/drivers/mmc/host/sdhci-of-sparx5.c index 14b5dad6575a..747f108a0ace 100644 --- a/drivers/mmc/host/sdhci-of-sparx5.c +++ b/drivers/mmc/host/sdhci-of-sparx5.c @@ -60,8 +60,8 @@ static void sdhci_sparx5_adma_write_desc(struct sdhci_host *host, void **desc, return; } - pr_debug("%s: write_desc: splitting dma len %d, offset 0x%0llx\n", - mmc_hostname(host->mmc), len, addr); + pr_debug("%s: write_desc: splitting dma len %d, offset %pad\n", + mmc_hostname(host->mmc), len, &addr); offset = addr & (SZ_128M - 1); tmplen = SZ_128M - offset; From b41123f4f57df6950f3316948989783bbdefa7e2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 2 Sep 2020 21:36:53 +0200 Subject: [PATCH 47/91] mmc: sdhci-brcmstb: Simplify with optional clock and dev_err_probe() Only -ENOENT from devm_clk_get() means that clock is not present in device tree. Other errors have their own meaning and should not be ignored. Simplify getting the clock which is in fact optional and also use dev_err_probe() for handling deferred. Signed-off-by: Krzysztof Kozlowski Acked-by: Florian Fainelli Link: https://lore.kernel.org/r/20200902193658.20539-7-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-brcmstb.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c index ad01f6451a95..876668827580 100644 --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -235,13 +235,11 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "Probe found match for %s\n", match->compatible); - clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(clk)) { - if (PTR_ERR(clk) == -EPROBE_DEFER) - return -EPROBE_DEFER; - dev_err(&pdev->dev, "Clock not found in Device Tree\n"); - clk = NULL; - } + clk = devm_clk_get_optional(&pdev->dev, NULL); + if (IS_ERR(clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(clk), + "Failed to get clock from Device Tree\n"); + res = clk_prepare_enable(clk); if (res) return res; From 8c7f51effd7387346e2754b545e224a68b9580ec Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 2 Sep 2020 22:48:45 +0200 Subject: [PATCH 48/91] mmc: davinci: Fix -Wpointer-to-int-cast on compile test Store in interrupt service routine always '1' in end_command, not the value of host->cmd to fix compile test warnings on RISC-V: drivers/mmc/host/davinci_mmc.c:999:17: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200902204847.2764-1-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/davinci_mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index fad1010fb52b..66d740ee7d45 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c @@ -996,7 +996,7 @@ static irqreturn_t mmc_davinci_irq(int irq, void *dev_id) if (qstatus & MMCST0_RSPDNE) { /* End of command phase */ - end_command = (int) host->cmd; + end_command = host->cmd ? 1 : 0; } if (end_command) From da4599992d3eff5e52a2b32f6e4099f19b1dd655 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 2 Sep 2020 22:48:46 +0200 Subject: [PATCH 49/91] mmc: s3cmci: Use proper printk format for iomem pointer iomem pointers should be printed with pointer format to hide the actual value and fix warnings when compile testing for 64-bit architecture: drivers/mmc/host/s3cmci.c:1355:46: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200902204847.2764-2-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/s3cmci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index b5df948f8155..477dcf417d4d 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -1376,7 +1376,7 @@ static int s3cmci_state_show(struct seq_file *seq, void *v) { struct s3cmci_host *host = seq->private; - seq_printf(seq, "Register base = 0x%08x\n", (u32)host->base); + seq_printf(seq, "Register base = 0x%p\n", host->base); seq_printf(seq, "Clock rate = %ld\n", host->clk_rate); seq_printf(seq, "Prescale = %d\n", host->prescaler); seq_printf(seq, "is2440 = %d\n", host->is2440); From 6e7fb09e1924927149b68e309d6524de777e54c2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 2 Sep 2020 22:48:47 +0200 Subject: [PATCH 50/91] mmc: s3cmci: Cast driver data through long Since driver data is a pointer, direct casting to integer causes warning when compile testing for 64-bit architecture: drivers/mmc/host/s3cmci.c:1495:17: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] The actual driver data can be only 0 or 1, so cast it via long and do not care about any loss of value. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200902204847.2764-3-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/s3cmci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 477dcf417d4d..704103a671e7 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -1519,7 +1519,7 @@ static int s3cmci_probe_dt(struct s3cmci_host *host) struct mmc_host *mmc = host->mmc; int ret; - host->is2440 = (int) of_device_get_match_data(&pdev->dev); + host->is2440 = (long) of_device_get_match_data(&pdev->dev); ret = mmc_of_parse(mmc); if (ret) From 4eabf0f20a2aa6e1e099faa816c4b9e9a2155891 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 3 Sep 2020 07:43:33 +0200 Subject: [PATCH 51/91] mmc: s3cmci: Drop unused variables in dbg_dumpregs The 'imask' and 'bsize' are not used in dbg_dumpregs: drivers/mmc/host/s3cmci.c:149:36: warning: variable 'imask' set but not used [-Wunused-but-set-variable] drivers/mmc/host/s3cmci.c:148:63: warning: variable 'bsize' set but not used [-Wunused-but-set-variable] Reported-by: kernel test robot Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200903054333.18331-1-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/s3cmci.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 704103a671e7..a725fb1abce7 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -150,8 +150,8 @@ static void s3cmci_reset(struct s3cmci_host *host); static void dbg_dumpregs(struct s3cmci_host *host, char *prefix) { - u32 con, pre, cmdarg, cmdcon, cmdsta, r0, r1, r2, r3, timer, bsize; - u32 datcon, datcnt, datsta, fsta, imask; + u32 con, pre, cmdarg, cmdcon, cmdsta, r0, r1, r2, r3, timer; + u32 datcon, datcnt, datsta, fsta; con = readl(host->base + S3C2410_SDICON); pre = readl(host->base + S3C2410_SDIPRE); @@ -163,12 +163,10 @@ static void dbg_dumpregs(struct s3cmci_host *host, char *prefix) r2 = readl(host->base + S3C2410_SDIRSP2); r3 = readl(host->base + S3C2410_SDIRSP3); timer = readl(host->base + S3C2410_SDITIMER); - bsize = readl(host->base + S3C2410_SDIBSIZE); datcon = readl(host->base + S3C2410_SDIDCON); datcnt = readl(host->base + S3C2410_SDIDCNT); datsta = readl(host->base + S3C2410_SDIDSTA); fsta = readl(host->base + S3C2410_SDIFSTA); - imask = readl(host->base + host->sdiimsk); dbg(host, dbg_debug, "%s CON:[%08x] PRE:[%08x] TMR:[%08x]\n", prefix, con, pre, timer); From 8c98644bfc45516c81dadb99ebd0f8461688add3 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Wed, 2 Sep 2020 16:43:15 -0700 Subject: [PATCH 52/91] mmc: sdhci-msm: Prefer asynchronous probe Turning on initcall debug on one system showed this: initcall sdhci_msm_driver_init+0x0/0x28 returned 0 after 34782 usecs The lion's share of this time (~33 ms) was in mmc_power_up(). This shouldn't be terribly surprising since there are a few calls to delay based on "power_delay_ms" and the default delay there is 10 ms. Because we haven't specified that we'd prefer asynchronous probe for this driver then we'll wait for this driver to finish before we start probes for more drivers. While 33 ms doesn't sound like tons, every little bit counts. There should be little problem with turning on asynchronous probe for this driver. It's already possible that previous drivers may have turned on asynchronous probe so we might already have other things (that probed before us) probing at the same time we are anyway. This driver isn't really providing resources (clocks, regulators, etc) that other drivers need to probe and even if it was they should be handling -EPROBE_DEFER. Let's turn this on and get a bit of boot speed back. Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20200902164303.1.I5e598a25222b4534c0083b61dbfa4e0e76f66171@changeid Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-msm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index d4c02884cca8..9dd0dbb65382 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -2542,6 +2542,7 @@ static struct platform_driver sdhci_msm_driver = { .name = "sdhci_msm", .of_match_table = sdhci_msm_dt_match, .pm = &sdhci_msm_pm_ops, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, }; From 24fdcb377892b44dfe9755a62e4b92e9c6a0b359 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 1 Sep 2020 17:02:47 +0200 Subject: [PATCH 53/91] mmc: core: when downgrading HS400, callback into drivers earlier The driver specific downgrade function makes more sense if we run it before we set the timing to something lower, not after. Otherwise some non-HS400 communication has already happened. No need to convert users. There is only one currently which needs this change in a following patch. Signed-off-by: Wolfram Sang Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20200901150250.26236-2-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/mmc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index b3fa193de846..ba2852b684b1 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1168,13 +1168,13 @@ static int mmc_select_hs400(struct mmc_card *card) return err; } - /* Set host controller to HS timing */ - mmc_set_timing(card->host, MMC_TIMING_MMC_HS); - /* Prepare host to downgrade to HS timing */ if (host->ops->hs400_downgrade) host->ops->hs400_downgrade(host); + /* Set host controller to HS timing */ + mmc_set_timing(card->host, MMC_TIMING_MMC_HS); + /* Reduce frequency to HS frequency */ max_dtr = card->ext_csd.hs_max_dtr; mmc_set_clock(host, max_dtr); @@ -1253,6 +1253,9 @@ int mmc_hs400_to_hs200(struct mmc_card *card) if (err) goto out_err; + if (host->ops->hs400_downgrade) + host->ops->hs400_downgrade(host); + mmc_set_timing(host, MMC_TIMING_MMC_DDR52); err = mmc_switch_status(card, true); @@ -1268,9 +1271,6 @@ int mmc_hs400_to_hs200(struct mmc_card *card) mmc_set_timing(host, MMC_TIMING_MMC_HS); - if (host->ops->hs400_downgrade) - host->ops->hs400_downgrade(host); - err = mmc_switch_status(card, true); if (err) goto out_err; From 97a7d87e96b02fc5b3944d7735e0f6b8446d07da Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 1 Sep 2020 17:02:48 +0200 Subject: [PATCH 54/91] mmc: core: add a 'doing_init_tune' flag and a 'mmc_doing_tune' helper Our driver needs to know when tuning is in progress. 'doing_retune' only covers re-tuning, not the initial tuning. Add another flag to detect the initial tuning state and add a helper which tells us if any kind of tuning is going on. Only implemented for MMC currently because that's where we need it. SD can be added later if it becomes necessary. Signed-off-by: Wolfram Sang Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20200901150250.26236-3-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/mmc.c | 4 ++++ include/linux/mmc/host.h | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index ba2852b684b1..216bd1aed373 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1763,6 +1763,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, goto free_card; if (mmc_card_hs200(card)) { + host->doing_init_tune = 1; + err = mmc_hs200_tuning(card); if (err) goto free_card; @@ -1770,6 +1772,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, err = mmc_select_hs400(card); if (err) goto free_card; + + host->doing_init_tune = 0; } else if (!mmc_card_hs400es(card)) { /* Select the desired bus width optionally */ err = mmc_select_bus_width(card); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 799e23b0a23c..c079b932330f 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -400,6 +400,7 @@ struct mmc_host { unsigned int use_spi_crc:1; unsigned int claimed:1; /* host exclusively claimed */ unsigned int bus_dead:1; /* bus has been released */ + unsigned int doing_init_tune:1; /* initial tuning in progress */ unsigned int can_retune:1; /* re-tuning can be used */ unsigned int doing_retune:1; /* re-tuning in progress */ unsigned int retune_now:1; /* do re-tuning at next req */ @@ -595,6 +596,11 @@ static inline bool mmc_doing_retune(struct mmc_host *host) return host->doing_retune == 1; } +static inline bool mmc_doing_tune(struct mmc_host *host) +{ + return host->doing_retune == 1 || host->doing_init_tune == 1; +} + static inline enum dma_data_direction mmc_get_dma_dir(struct mmc_data *data) { return data->flags & MMC_DATA_WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE; From 0f93db6542fa94262b611ff942b9b3ad7ecbea10 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 1 Sep 2020 17:02:49 +0200 Subject: [PATCH 55/91] mmc: renesas_sdhi: keep SCC clock active when tuning Tuning procedure switches to lower frequencies but that will turn the SCC off and accessing its register then will hang. So, check when we are tuning and keep the current setup of the external clock if we are doing so. Note that we still switch to the lower frequency because of the internal divider. We just make sure to not modify the external clock. This patch depends on a MMC core patch calling the downgrade function earlier. Signed-off-by: Wolfram Sang Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20200901150250.26236-4-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 1243c42d3d1b..42eaec40a6d9 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -117,8 +117,12 @@ static unsigned int renesas_sdhi_clk_update(struct tmio_mmc_host *host, unsigned int freq, diff, best_freq = 0, diff_min = ~0; int i; - /* tested only on R-Car Gen2+ currently; may work for others */ - if (!(host->pdata->flags & TMIO_MMC_MIN_RCAR2)) + /* + * We simply return the current rate if a) we are not on a R-Car Gen2+ + * SoC (may work for others, but untested) or b) if the SCC needs its + * clock during tuning, so we don't change the external clock setup. + */ + if (!(host->pdata->flags & TMIO_MMC_MIN_RCAR2) || mmc_doing_tune(host->mmc)) return clk_get_rate(priv->clk); /* From 452f553e272cf010ee1ac2d4896b265a6fbf4e29 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 1 Sep 2020 17:02:50 +0200 Subject: [PATCH 56/91] mmc: core: simplify an expression We already have 'host' as a variable, so use it. Signed-off-by: Wolfram Sang Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20200901150250.26236-5-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 216bd1aed373..67e95eba0e82 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1173,7 +1173,7 @@ static int mmc_select_hs400(struct mmc_card *card) host->ops->hs400_downgrade(host); /* Set host controller to HS timing */ - mmc_set_timing(card->host, MMC_TIMING_MMC_HS); + mmc_set_timing(host, MMC_TIMING_MMC_HS); /* Reduce frequency to HS frequency */ max_dtr = card->ext_csd.hs_max_dtr; From 77811ffa6f66ae4051451b0a9ebb22b2b1fdd466 Mon Sep 17 00:00:00 2001 From: Xu Wang Date: Thu, 3 Sep 2020 08:48:25 +0000 Subject: [PATCH 57/91] mmc: omap-hsmmc: remove redundant null check Because clk_disable_unprepare already checked NULL clock parameter, so the additional checks are unnecessary, just remove them. Signed-off-by: Xu Wang Link: https://lore.kernel.org/r/20200903084825.85616-1-vulab@iscas.ac.cn Signed-off-by: Ulf Hansson --- drivers/mmc/host/omap_hsmmc.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 37b8740513f5..d02983e23ed1 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1114,8 +1114,7 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd) int ret; /* Disable the clocks */ - if (host->dbclk) - clk_disable_unprepare(host->dbclk); + clk_disable_unprepare(host->dbclk); /* Turn the power off */ ret = omap_hsmmc_set_power(host, 0); @@ -1123,8 +1122,7 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd) /* Turn the power ON with given VDD 1.8 or 3.0v */ if (!ret) ret = omap_hsmmc_set_power(host, 1); - if (host->dbclk) - clk_prepare_enable(host->dbclk); + clk_prepare_enable(host->dbclk); if (ret != 0) goto err; @@ -2014,8 +2012,7 @@ err_irq: pm_runtime_dont_use_autosuspend(host->dev); pm_runtime_put_sync(host->dev); pm_runtime_disable(host->dev); - if (host->dbclk) - clk_disable_unprepare(host->dbclk); + clk_disable_unprepare(host->dbclk); err1: mmc_free_host(mmc); err: @@ -2037,8 +2034,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev) pm_runtime_put_sync(host->dev); pm_runtime_disable(host->dev); device_init_wakeup(&pdev->dev, false); - if (host->dbclk) - clk_disable_unprepare(host->dbclk); + clk_disable_unprepare(host->dbclk); mmc_free_host(host->mmc); @@ -2063,8 +2059,7 @@ static int omap_hsmmc_suspend(struct device *dev) OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); } - if (host->dbclk) - clk_disable_unprepare(host->dbclk); + clk_disable_unprepare(host->dbclk); pm_runtime_put_sync(host->dev); return 0; @@ -2080,8 +2075,7 @@ static int omap_hsmmc_resume(struct device *dev) pm_runtime_get_sync(host->dev); - if (host->dbclk) - clk_prepare_enable(host->dbclk); + clk_prepare_enable(host->dbclk); if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) omap_hsmmc_conf_bus_power(host); From 55118e5358343c74b7a607d5b9251df8acc3fca9 Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Thu, 3 Sep 2020 22:18:06 +0100 Subject: [PATCH 58/91] mmc: renesas_sdhi: Drop local dma_parms Since commit 9495b7e92f71 ("driver core: platform: Initialize dma_parms for platform devices"), struct platform_device already provides a dma_parms structure, so we can save allocating another one. Signed-off-by: Robin Murphy Reviewed-by: Wolfram Sang Tested-by: Wolfram Sang Link: https://lore.kernel.org/r/85e1fc97dbec3dea96102785a5e308ccb5e91cfe.1599167798.git.robin.murphy@arm.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_internal_dmac.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index 32ab991544ef..8ee6b2b85ec2 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -336,10 +336,6 @@ static int renesas_sdhi_internal_dmac_probe(struct platform_device *pdev) if (soc) global_flags |= (unsigned long)soc->data; - dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), GFP_KERNEL); - if (!dev->dma_parms) - return -ENOMEM; - /* value is max of SD_SECCNT. Confirmed by HW engineers */ dma_set_max_seg_size(dev, 0xffffffff); From f5d373ec2822fa0f3d52cec9a086115140e7d4e7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 4 Sep 2020 18:43:14 +0200 Subject: [PATCH 59/91] mmc: host: Drop unneeded MMC dependency in Kconfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All entries in Kconfig are already part of "if MMC", so there is no need for additional dependency on MMC. Suggested-by: Michał Mirosław Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200904164315.24618-1-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 0af8b12a8f7d..ddbed6f41c41 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -422,7 +422,7 @@ config MMC_SDHCI_IPROC config MMC_MESON_GX tristate "Amlogic S905/GX*/AXG SD/MMC Host Controller support" - depends on ARCH_MESON && MMC + depends on ARCH_MESON help This selects support for the Amlogic SD/MMC Host Controller found on the S905/GX*/AXG family of SoCs. This controller is @@ -458,7 +458,7 @@ config MMC_MESON_MX_SDIO config MMC_MOXART tristate "MOXART SD/MMC Host Controller support" - depends on ARCH_MOXART && MMC + depends on ARCH_MOXART help This selects support for the MOXART SD/MMC Host Controller. MOXA provides one multi-functional card reader which can From 54d8454436a205682bd89d66d8d9eedbc8452d15 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 7 Sep 2020 12:52:54 +0200 Subject: [PATCH 60/91] mmc: host: Enable compile testing of multiple drivers Multiple MMC host controller driver can be compile tested as they do not depend on architecture specific headers. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200907105254.31097-1-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/Kconfig | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index ddbed6f41c41..dc646359b4ff 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -178,7 +178,7 @@ config MMC_SDHCI_OF_AT91 config MMC_SDHCI_OF_ESDHC tristate "SDHCI OF support for the Freescale eSDHC controller" depends on MMC_SDHCI_PLTFM - depends on PPC || ARCH_MXC || ARCH_LAYERSCAPE + depends on PPC || ARCH_MXC || ARCH_LAYERSCAPE || COMPILE_TEST select MMC_SDHCI_IO_ACCESSORS select FSL_GUTS help @@ -216,7 +216,7 @@ config MMC_SDHCI_OF_DWCMSHC config MMC_SDHCI_OF_SPARX5 tristate "SDHCI OF support for the MCHP Sparx5 SoC" depends on MMC_SDHCI_PLTFM - depends on ARCH_SPARX5 + depends on ARCH_SPARX5 || COMPILE_TEST help This selects the Secure Digital Host Controller Interface (SDHCI) found in the MCHP Sparx5 SoC. @@ -238,7 +238,7 @@ config MMC_SDHCI_CADENCE config MMC_SDHCI_CNS3XXX tristate "SDHCI support on the Cavium Networks CNS3xxx SoC" - depends on ARCH_CNS3XXX + depends on ARCH_CNS3XXX || COMPILE_TEST depends on MMC_SDHCI_PLTFM help This selects the SDHCI support for CNS3xxx System-on-Chip devices. @@ -262,7 +262,7 @@ config MMC_SDHCI_ESDHC_MCF config MMC_SDHCI_ESDHC_IMX tristate "SDHCI support for the Freescale eSDHC/uSDHC i.MX controller" - depends on ARCH_MXC + depends on ARCH_MXC || COMPILE_TEST depends on MMC_SDHCI_PLTFM select MMC_SDHCI_IO_ACCESSORS select MMC_CQHCI @@ -276,7 +276,7 @@ config MMC_SDHCI_ESDHC_IMX config MMC_SDHCI_DOVE tristate "SDHCI support on Marvell's Dove SoC" - depends on ARCH_DOVE || MACH_DOVE + depends on ARCH_DOVE || MACH_DOVE || COMPILE_TEST depends on MMC_SDHCI_PLTFM select MMC_SDHCI_IO_ACCESSORS help @@ -289,7 +289,7 @@ config MMC_SDHCI_DOVE config MMC_SDHCI_TEGRA tristate "SDHCI platform support for the Tegra SD/MMC Controller" - depends on ARCH_TEGRA + depends on ARCH_TEGRA || COMPILE_TEST depends on MMC_SDHCI_PLTFM select MMC_SDHCI_IO_ACCESSORS select MMC_CQHCI @@ -301,7 +301,8 @@ config MMC_SDHCI_TEGRA config MMC_SDHCI_S3C tristate "SDHCI support on Samsung S3C SoC" - depends on MMC_SDHCI && PLAT_SAMSUNG + depends on MMC_SDHCI + depends on PLAT_SAMSUNG || COMPILE_TEST help This selects the Secure Digital Host Controller Interface (SDHCI) often referrered to as the HSMMC block in some of the Samsung S3C @@ -313,7 +314,7 @@ config MMC_SDHCI_S3C config MMC_SDHCI_SIRF tristate "SDHCI support on CSR SiRFprimaII and SiRFmarco SoCs" - depends on ARCH_SIRF + depends on ARCH_SIRF || COMPILE_TEST depends on MMC_SDHCI_PLTFM select MMC_SDHCI_IO_ACCESSORS help @@ -351,7 +352,8 @@ config MMC_SDHCI_PXAV2 config MMC_SDHCI_SPEAR tristate "SDHCI support on ST SPEAr platform" - depends on MMC_SDHCI && PLAT_SPEAR + depends on MMC_SDHCI + depends on PLAT_SPEAR || COMPILE_TEST depends on OF help This selects the Secure Digital Host Controller Interface (SDHCI) @@ -374,7 +376,7 @@ config MMC_SDHCI_S3C_DMA config MMC_SDHCI_BCM_KONA tristate "SDHCI support on Broadcom KONA platform" - depends on ARCH_BCM_MOBILE + depends on ARCH_BCM_MOBILE || COMPILE_TEST depends on MMC_SDHCI_PLTFM help This selects the Broadcom Kona Secure Digital Host Controller @@ -422,7 +424,7 @@ config MMC_SDHCI_IPROC config MMC_MESON_GX tristate "Amlogic S905/GX*/AXG SD/MMC Host Controller support" - depends on ARCH_MESON + depends on ARCH_MESON|| COMPILE_TEST help This selects support for the Amlogic SD/MMC Host Controller found on the S905/GX*/AXG family of SoCs. This controller is @@ -458,7 +460,7 @@ config MMC_MESON_MX_SDIO config MMC_MOXART tristate "MOXART SD/MMC Host Controller support" - depends on ARCH_MOXART + depends on ARCH_MOXART || COMPILE_TEST help This selects support for the MOXART SD/MMC Host Controller. MOXA provides one multi-functional card reader which can @@ -467,7 +469,7 @@ config MMC_MOXART config MMC_SDHCI_ST tristate "SDHCI support on STMicroelectronics SoC" - depends on ARCH_STI || FSP2 + depends on ARCH_STI || FSP2 || COMPILE_TEST depends on MMC_SDHCI_PLTFM select MMC_SDHCI_IO_ACCESSORS help @@ -587,7 +589,7 @@ config MMC_TIFM_SD config MMC_MVSDIO tristate "Marvell MMC/SD/SDIO host driver" - depends on PLAT_ORION + depends on PLAT_ORION || (COMPILE_TEST && ARM) depends on OF help This selects the Marvell SDIO host driver. @@ -599,7 +601,7 @@ config MMC_MVSDIO config MMC_DAVINCI tristate "TI DAVINCI Multimedia Card Interface support" - depends on ARCH_DAVINCI + depends on ARCH_DAVINCI || COMPILE_TEST help This selects the TI DAVINCI Multimedia card Interface. If you have an DAVINCI board with a Multimedia Card slot, @@ -628,7 +630,7 @@ config MMC_SPI config MMC_S3C tristate "Samsung S3C SD/MMC Card Interface support" - depends on ARCH_S3C24XX + depends on ARCH_S3C24XX || COMPILE_TEST depends on S3C24XX_DMAC help This selects a driver for the MCI interface found in @@ -681,7 +683,7 @@ config MMC_SDRICOH_CS config MMC_SDHCI_SPRD tristate "Spreadtrum SDIO host Controller" - depends on ARCH_SPRD + depends on ARCH_SPRD || COMPILE_TEST depends on MMC_SDHCI_PLTFM select MMC_SDHCI_IO_ACCESSORS select MMC_HSQ @@ -698,7 +700,7 @@ config MMC_TMIO_CORE config MMC_TMIO tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support" - depends on MFD_TMIO || MFD_ASIC3 + depends on MFD_TMIO || MFD_ASIC3 || COMPILE_TEST select MMC_TMIO_CORE help This provides support for the SD/MMC cell found in TC6393XB, @@ -971,7 +973,7 @@ config MMC_REALTEK_USB config MMC_SUNXI tristate "Allwinner sunxi SD/MMC Host Controller support" - depends on ARCH_SUNXI + depends on ARCH_SUNXI || COMPILE_TEST help This selects support for the SD/MMC Host Controller on Allwinner sunxi SoCs. From 21b2cec61c04bd175f0860d9411a472d5a0e7ba1 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 3 Sep 2020 16:24:36 -0700 Subject: [PATCH 61/91] mmc: Set PROBE_PREFER_ASYNCHRONOUS for drivers that existed in v4.4 This is like commit 3d3451124f3d ("mmc: sdhci-msm: Prefer asynchronous probe") but applied to a whole pile of drivers. This batch converts the drivers that appeared to be around in the v4.4 timeframe. Signed-off-by: Douglas Anderson Reviewed-by: Wolfram Sang Tested-by: Wolfram Sang # SH_MMCIF Tested-by: Thierry Reding Link: https://lore.kernel.org/r/20200903162412.1.Id501e96fa63224f77bb86b2135a5e8324ffb9c43@changeid Signed-off-by: Ulf Hansson --- drivers/mmc/host/android-goldfish.c | 1 + drivers/mmc/host/atmel-mci.c | 1 + drivers/mmc/host/au1xmmc.c | 1 + drivers/mmc/host/davinci_mmc.c | 1 + drivers/mmc/host/dw_mmc-exynos.c | 1 + drivers/mmc/host/dw_mmc-k3.c | 1 + drivers/mmc/host/dw_mmc-pltfm.c | 1 + drivers/mmc/host/dw_mmc-rockchip.c | 1 + drivers/mmc/host/jz4740_mmc.c | 1 + drivers/mmc/host/moxart-mmc.c | 1 + drivers/mmc/host/mtk-sd.c | 1 + drivers/mmc/host/mvsdio.c | 1 + drivers/mmc/host/mxcmmc.c | 1 + drivers/mmc/host/mxs-mmc.c | 1 + drivers/mmc/host/omap.c | 1 + drivers/mmc/host/omap_hsmmc.c | 1 + drivers/mmc/host/pxamci.c | 1 + drivers/mmc/host/rtsx_pci_sdmmc.c | 1 + drivers/mmc/host/rtsx_usb_sdmmc.c | 1 + drivers/mmc/host/s3cmci.c | 1 + drivers/mmc/host/sdhci-acpi.c | 1 + drivers/mmc/host/sdhci-bcm-kona.c | 1 + drivers/mmc/host/sdhci-cns3xxx.c | 1 + drivers/mmc/host/sdhci-dove.c | 1 + drivers/mmc/host/sdhci-esdhc-imx.c | 1 + drivers/mmc/host/sdhci-iproc.c | 1 + drivers/mmc/host/sdhci-of-arasan.c | 1 + drivers/mmc/host/sdhci-of-at91.c | 1 + drivers/mmc/host/sdhci-of-esdhc.c | 1 + drivers/mmc/host/sdhci-of-hlwd.c | 1 + drivers/mmc/host/sdhci-pxav2.c | 1 + drivers/mmc/host/sdhci-pxav3.c | 1 + drivers/mmc/host/sdhci-s3c.c | 1 + drivers/mmc/host/sdhci-sirf.c | 1 + drivers/mmc/host/sdhci-spear.c | 1 + drivers/mmc/host/sdhci-st.c | 1 + drivers/mmc/host/sdhci-tegra.c | 1 + drivers/mmc/host/sdhci_f_sdh30.c | 1 + drivers/mmc/host/sh_mmcif.c | 1 + drivers/mmc/host/sunxi-mmc.c | 1 + drivers/mmc/host/tmio_mmc.c | 1 + drivers/mmc/host/usdhi6rol0.c | 1 + drivers/mmc/host/wbsd.c | 1 + drivers/mmc/host/wmt-sdmmc.c | 1 + 44 files changed, 44 insertions(+) diff --git a/drivers/mmc/host/android-goldfish.c b/drivers/mmc/host/android-goldfish.c index ceb4924e02d0..e878fdf8f20a 100644 --- a/drivers/mmc/host/android-goldfish.c +++ b/drivers/mmc/host/android-goldfish.c @@ -537,6 +537,7 @@ static struct platform_driver goldfish_mmc_driver = { .remove = goldfish_mmc_remove, .driver = { .name = DRIVER_NAME, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, }; diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 3fc3bbea8536..444bd3a0a922 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -2668,6 +2668,7 @@ static struct platform_driver atmci_driver = { .remove = atmci_remove, .driver = { .name = "atmel_mci", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(atmci_dt_ids), .pm = &atmci_dev_pm_ops, }, diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index 9bb1910268ca..bd00515fbaba 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c @@ -1189,6 +1189,7 @@ static struct platform_driver au1xmmc_driver = { .resume = au1xmmc_resume, .driver = { .name = DRIVER_NAME, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, }; diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index 66d740ee7d45..90cd179625fc 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c @@ -1395,6 +1395,7 @@ static const struct dev_pm_ops davinci_mmcsd_pm = { static struct platform_driver davinci_mmcsd_driver = { .driver = { .name = "davinci_mmc", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = davinci_mmcsd_pm_ops, .of_match_table = davinci_mmc_dt_ids, }, diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 95adeee07217..0c75810812a0 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -592,6 +592,7 @@ static struct platform_driver dw_mci_exynos_pltfm_driver = { .remove = dw_mci_exynos_remove, .driver = { .name = "dwmmc_exynos", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = dw_mci_exynos_match, .pm = &dw_mci_exynos_pmops, }, diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c index db1a84b2ba61..29d2494eb27a 100644 --- a/drivers/mmc/host/dw_mmc-k3.c +++ b/drivers/mmc/host/dw_mmc-k3.c @@ -473,6 +473,7 @@ static struct platform_driver dw_mci_k3_pltfm_driver = { .remove = dw_mci_pltfm_remove, .driver = { .name = "dwmmc_k3", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = dw_mci_k3_match, .pm = &dw_mci_k3_dev_pm_ops, }, diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 7de37f524a96..73731cd3ba23 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -98,6 +98,7 @@ static struct platform_driver dw_mci_pltfm_driver = { .remove = dw_mci_pltfm_remove, .driver = { .name = "dw_mmc", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = dw_mci_pltfm_match, .pm = &dw_mci_pltfm_pmops, }, diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c index d4d02134848c..753502ce3c85 100644 --- a/drivers/mmc/host/dw_mmc-rockchip.c +++ b/drivers/mmc/host/dw_mmc-rockchip.c @@ -383,6 +383,7 @@ static struct platform_driver dw_mci_rockchip_pltfm_driver = { .remove = dw_mci_rockchip_remove, .driver = { .name = "dwmmc_rockchip", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = dw_mci_rockchip_match, .pm = &dw_mci_rockchip_dev_pm_ops, }, diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index fea0a42010c7..a1f92fed2a55 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -1124,6 +1124,7 @@ static struct platform_driver jz4740_mmc_driver = { .remove = jz4740_mmc_remove, .driver = { .name = "jz4740-mmc", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(jz4740_mmc_of_match), .pm = pm_ptr(&jz4740_mmc_pm_ops), }, diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c index fc6b9cf27d0b..2bfb376fddc4 100644 --- a/drivers/mmc/host/moxart-mmc.c +++ b/drivers/mmc/host/moxart-mmc.c @@ -717,6 +717,7 @@ static struct platform_driver moxart_mmc_driver = { .remove = moxart_remove, .driver = { .name = "mmc-moxart", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = moxart_mmc_match, }, }; diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index ed2b24691b4f..691c928edab7 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -2689,6 +2689,7 @@ static struct platform_driver mt_msdc_driver = { .remove = msdc_drv_remove, .driver = { .name = "mtk-msdc", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = msdc_of_ids, .pm = &msdc_dev_pm_ops, }, diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index cc0752a9df6d..629efbe639c4 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c @@ -824,6 +824,7 @@ static struct platform_driver mvsd_driver = { .remove = mvsd_remove, .driver = { .name = DRIVER_NAME, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = mvsdio_dt_ids, }, }; diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index b3d654c688e5..12ee07285980 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -1244,6 +1244,7 @@ static struct platform_driver mxcmci_driver = { .id_table = mxcmci_devtype, .driver = { .name = DRIVER_NAME, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &mxcmci_pm_ops, .of_match_table = mxcmci_of_match, } diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index b1820def36c0..75007f61df97 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -726,6 +726,7 @@ static struct platform_driver mxs_mmc_driver = { .id_table = mxs_ssp_ids, .driver = { .name = DRIVER_NAME, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &mxs_mmc_pm_ops, .of_match_table = mxs_mmc_dt_ids, }, diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 33d7af7c7762..6aa0537f1f84 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -1504,6 +1504,7 @@ static struct platform_driver mmc_omap_driver = { .remove = mmc_omap_remove, .driver = { .name = DRIVER_NAME, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(mmc_omap_match), }, }; diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index d02983e23ed1..aa9cc49206d1 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2165,6 +2165,7 @@ static struct platform_driver omap_hsmmc_driver = { .remove = omap_hsmmc_remove, .driver = { .name = DRIVER_NAME, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &omap_hsmmc_dev_pm_ops, .of_match_table = of_match_ptr(omap_mmc_of_match), }, diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 3a9333475a2b..29f6180a0036 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -811,6 +811,7 @@ static struct platform_driver pxamci_driver = { .remove = pxamci_remove, .driver = { .name = DRIVER_NAME, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(pxa_mmc_dt_ids), }, }; diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index 2763a376b054..eb395e144207 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c @@ -1471,6 +1471,7 @@ static struct platform_driver rtsx_pci_sdmmc_driver = { .id_table = rtsx_pci_sdmmc_ids, .driver = { .name = DRV_NAME_RTSX_PCI_SDMMC, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, }; module_platform_driver(rtsx_pci_sdmmc_driver); diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c index 7225d9312af8..598f49573f5d 100644 --- a/drivers/mmc/host/rtsx_usb_sdmmc.c +++ b/drivers/mmc/host/rtsx_usb_sdmmc.c @@ -1458,6 +1458,7 @@ static struct platform_driver rtsx_usb_sdmmc_driver = { .id_table = rtsx_usb_sdmmc_ids, .driver = { .name = "rtsx_usb_sdmmc", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &rtsx_usb_sdmmc_dev_pm_ops, }, }; diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index a725fb1abce7..e3698aba8dd3 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -1804,6 +1804,7 @@ MODULE_DEVICE_TABLE(platform, s3cmci_driver_ids); static struct platform_driver s3cmci_driver = { .driver = { .name = "s3c-sdi", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = s3cmci_dt_match, }, .id_table = s3cmci_driver_ids, diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 284cba11e279..fc41d0451f20 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -1027,6 +1027,7 @@ static const struct dev_pm_ops sdhci_acpi_pm_ops = { static struct platform_driver sdhci_acpi_driver = { .driver = { .name = "sdhci-acpi", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .acpi_match_table = sdhci_acpi_ids, .pm = &sdhci_acpi_pm_ops, }, diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c index a6c2bd202b45..4d4aac85cc7a 100644 --- a/drivers/mmc/host/sdhci-bcm-kona.c +++ b/drivers/mmc/host/sdhci-bcm-kona.c @@ -324,6 +324,7 @@ err_pltfm_free: static struct platform_driver sdhci_bcm_kona_driver = { .driver = { .name = "sdhci-kona", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &sdhci_pltfm_pmops, .of_match_table = sdhci_bcm_kona_of_match, }, diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c index 811eab1b8964..2a29c7a4f308 100644 --- a/drivers/mmc/host/sdhci-cns3xxx.c +++ b/drivers/mmc/host/sdhci-cns3xxx.c @@ -98,6 +98,7 @@ static int sdhci_cns3xxx_probe(struct platform_device *pdev) static struct platform_driver sdhci_cns3xxx_driver = { .driver = { .name = "sdhci-cns3xxx", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &sdhci_pltfm_pmops, }, .probe = sdhci_cns3xxx_probe, diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index fe9da3122fe9..5e5bf82e5976 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c @@ -105,6 +105,7 @@ MODULE_DEVICE_TABLE(of, sdhci_dove_of_match_table); static struct platform_driver sdhci_dove_driver = { .driver = { .name = "sdhci-dove", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &sdhci_pltfm_pmops, .of_match_table = sdhci_dove_of_match_table, }, diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index a2eb36c9b1da..62b3d4767916 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -1925,6 +1925,7 @@ static const struct dev_pm_ops sdhci_esdhc_pmops = { static struct platform_driver sdhci_esdhc_imx_driver = { .driver = { .name = "sdhci-esdhc-imx", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = imx_esdhc_dt_ids, .pm = &sdhci_esdhc_pmops, }, diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c index b540aa6faacb..c9434b461aab 100644 --- a/drivers/mmc/host/sdhci-iproc.c +++ b/drivers/mmc/host/sdhci-iproc.c @@ -369,6 +369,7 @@ err: static struct platform_driver sdhci_iproc_driver = { .driver = { .name = "sdhci-iproc", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = sdhci_iproc_of_match, .acpi_match_table = ACPI_PTR(sdhci_iproc_acpi_ids), .pm = &sdhci_pltfm_pmops, diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index 3aea46db2ea7..829ccef87426 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -1693,6 +1693,7 @@ static int sdhci_arasan_remove(struct platform_device *pdev) static struct platform_driver sdhci_arasan_driver = { .driver = { .name = "sdhci-arasan", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = sdhci_arasan_of_match, .pm = &sdhci_arasan_dev_pm_ops, }, diff --git a/drivers/mmc/host/sdhci-of-at91.c b/drivers/mmc/host/sdhci-of-at91.c index 1ece2c50042c..5564d7b23e7c 100644 --- a/drivers/mmc/host/sdhci-of-at91.c +++ b/drivers/mmc/host/sdhci-of-at91.c @@ -465,6 +465,7 @@ static int sdhci_at91_remove(struct platform_device *pdev) static struct platform_driver sdhci_at91_driver = { .driver = { .name = "sdhci-at91", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = sdhci_at91_dt_match, .pm = &sdhci_at91_dev_pm_ops, }, diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 45881b309956..3a3340c9b8c9 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -1468,6 +1468,7 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) static struct platform_driver sdhci_esdhc_driver = { .driver = { .name = "sdhci-esdhc", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = sdhci_esdhc_of_match, .pm = &esdhc_of_dev_pm_ops, }, diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c index da844a39af6e..12675797b296 100644 --- a/drivers/mmc/host/sdhci-of-hlwd.c +++ b/drivers/mmc/host/sdhci-of-hlwd.c @@ -80,6 +80,7 @@ MODULE_DEVICE_TABLE(of, sdhci_hlwd_of_match); static struct platform_driver sdhci_hlwd_driver = { .driver = { .name = "sdhci-hlwd", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = sdhci_hlwd_of_match, .pm = &sdhci_pltfm_pmops, }, diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c index 9282bc4b8c41..f18906b5575f 100644 --- a/drivers/mmc/host/sdhci-pxav2.c +++ b/drivers/mmc/host/sdhci-pxav2.c @@ -226,6 +226,7 @@ free: static struct platform_driver sdhci_pxav2_driver = { .driver = { .name = "sdhci-pxav2", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(sdhci_pxav2_of_match), .pm = &sdhci_pltfm_pmops, }, diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index e55037ceda73..a6d89a3f1946 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -567,6 +567,7 @@ static const struct dev_pm_ops sdhci_pxav3_pmops = { static struct platform_driver sdhci_pxav3_driver = { .driver = { .name = "sdhci-pxav3", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(sdhci_pxav3_of_match), .pm = &sdhci_pxav3_pmops, }, diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 080ced1e63f0..cb5f87be7535 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -784,6 +784,7 @@ static struct platform_driver sdhci_s3c_driver = { .id_table = sdhci_s3c_driver_ids, .driver = { .name = "s3c-sdhci", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(sdhci_s3c_dt_match), .pm = &sdhci_s3c_pmops, }, diff --git a/drivers/mmc/host/sdhci-sirf.c b/drivers/mmc/host/sdhci-sirf.c index f4b05dd6c20a..e9b347b3af7e 100644 --- a/drivers/mmc/host/sdhci-sirf.c +++ b/drivers/mmc/host/sdhci-sirf.c @@ -220,6 +220,7 @@ MODULE_DEVICE_TABLE(of, sdhci_sirf_of_match); static struct platform_driver sdhci_sirf_driver = { .driver = { .name = "sdhci-sirf", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = sdhci_sirf_of_match, .pm = &sdhci_pltfm_pmops, }, diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c index b4b63089a4e2..d463e2fd5b1a 100644 --- a/drivers/mmc/host/sdhci-spear.c +++ b/drivers/mmc/host/sdhci-spear.c @@ -181,6 +181,7 @@ MODULE_DEVICE_TABLE(of, sdhci_spear_id_table); static struct platform_driver sdhci_driver = { .driver = { .name = "sdhci", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &sdhci_pm_ops, .of_match_table = of_match_ptr(sdhci_spear_id_table), }, diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index 1301cebfc3ea..4e9ff3e828ba 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c @@ -521,6 +521,7 @@ static struct platform_driver sdhci_st_driver = { .remove = sdhci_st_remove, .driver = { .name = "sdhci-st", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &sdhci_st_pmops, .of_match_table = of_match_ptr(st_sdhci_match), }, diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 428cdc53c858..ed12aacb1c73 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -1782,6 +1782,7 @@ static SIMPLE_DEV_PM_OPS(sdhci_tegra_dev_pm_ops, sdhci_tegra_suspend, static struct platform_driver sdhci_tegra_driver = { .driver = { .name = "sdhci-tegra", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = sdhci_tegra_dt_match, .pm = &sdhci_tegra_dev_pm_ops, }, diff --git a/drivers/mmc/host/sdhci_f_sdh30.c b/drivers/mmc/host/sdhci_f_sdh30.c index 4625cc071b61..3f5977979cf2 100644 --- a/drivers/mmc/host/sdhci_f_sdh30.c +++ b/drivers/mmc/host/sdhci_f_sdh30.c @@ -219,6 +219,7 @@ MODULE_DEVICE_TABLE(acpi, f_sdh30_acpi_ids); static struct platform_driver sdhci_f_sdh30_driver = { .driver = { .name = "f_sdh30", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(f_sdh30_dt_ids), .acpi_match_table = ACPI_PTR(f_sdh30_acpi_ids), .pm = &sdhci_pltfm_pmops, diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 9f53634aa411..e5e457037235 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1562,6 +1562,7 @@ static struct platform_driver sh_mmcif_driver = { .remove = sh_mmcif_remove, .driver = { .name = DRIVER_NAME, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &sh_mmcif_dev_pm_ops, .of_match_table = sh_mmcif_of_match, }, diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index 5e95bbc51644..fc62773602ec 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -1514,6 +1514,7 @@ static const struct dev_pm_ops sunxi_mmc_pm_ops = { static struct platform_driver sunxi_mmc_driver = { .driver = { .name = "sunxi-mmc", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(sunxi_mmc_of_match), .pm = &sunxi_mmc_pm_ops, }, diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 757c90160ae4..d2d3b8df1bbe 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -213,6 +213,7 @@ static const struct dev_pm_ops tmio_mmc_dev_pm_ops = { static struct platform_driver tmio_mmc_driver = { .driver = { .name = "tmio-mmc", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &tmio_mmc_dev_pm_ops, }, .probe = tmio_mmc_probe, diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c index 7666c90054ae..e2d5112d809d 100644 --- a/drivers/mmc/host/usdhi6rol0.c +++ b/drivers/mmc/host/usdhi6rol0.c @@ -1890,6 +1890,7 @@ static struct platform_driver usdhi6_driver = { .remove = usdhi6_remove, .driver = { .name = "usdhi6rol0", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = usdhi6_of_match, }, }; diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c index 67f917d6ecd3..cd63ea865b77 100644 --- a/drivers/mmc/host/wbsd.c +++ b/drivers/mmc/host/wbsd.c @@ -1905,6 +1905,7 @@ static struct platform_driver wbsd_driver = { .resume = wbsd_platform_resume, .driver = { .name = DRIVER_NAME, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, }; diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c index 2c4ba1fa4bbf..cf10949fb0ac 100644 --- a/drivers/mmc/host/wmt-sdmmc.c +++ b/drivers/mmc/host/wmt-sdmmc.c @@ -990,6 +990,7 @@ static struct platform_driver wmt_mci_driver = { .remove = wmt_mci_remove, .driver = { .name = DRIVER_NAME, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = wmt_mci_pm_ops, .of_match_table = wmt_mci_dt_ids, }, From 2a99f3fa85eaa79c332945a256ff63aad1fd0b9c Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 3 Sep 2020 16:24:37 -0700 Subject: [PATCH 62/91] mmc: Set PROBE_PREFER_ASYNCHRONOUS for drivers that existed in v4.9 This is like commit 3d3451124f3d ("mmc: sdhci-msm: Prefer asynchronous probe") but applied to a whole pile of drivers. This batch converts the drivers that appeared to be around in the v4.9 timeframe. Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20200903162412.2.I226782b43191ce367fa3bc1c907c29f571890412@changeid Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-brcmstb.c | 1 + drivers/mmc/host/sdhci-pic32.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c index 876668827580..bbf3496f4495 100644 --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -326,6 +326,7 @@ MODULE_DEVICE_TABLE(of, sdhci_brcm_of_match); static struct platform_driver sdhci_brcmstb_driver = { .driver = { .name = "sdhci-brcmstb", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &sdhci_pltfm_pmops, .of_match_table = of_match_ptr(sdhci_brcm_of_match), }, diff --git a/drivers/mmc/host/sdhci-pic32.c b/drivers/mmc/host/sdhci-pic32.c index a11e6397d4ff..6ce1519ae177 100644 --- a/drivers/mmc/host/sdhci-pic32.c +++ b/drivers/mmc/host/sdhci-pic32.c @@ -241,6 +241,7 @@ MODULE_DEVICE_TABLE(of, pic32_sdhci_id_table); static struct platform_driver pic32_sdhci_driver = { .driver = { .name = "pic32-sdhci", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(pic32_sdhci_id_table), }, .probe = pic32_sdhci_probe, From 7320915c88618050a2f65a193f0e25cccb2007b6 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 3 Sep 2020 16:24:38 -0700 Subject: [PATCH 63/91] mmc: Set PROBE_PREFER_ASYNCHRONOUS for drivers that existed in v4.14 This is like commit 3d3451124f3d ("mmc: sdhci-msm: Prefer asynchronous probe") but applied to a whole pile of drivers. This batch converts the drivers that appeared to be around in the v4.14 timeframe. Signed-off-by: Douglas Anderson Reviewed-by: Wolfram Sang Tested-by: Wolfram Sang # SDHI drivers Link: https://lore.kernel.org/r/20200903162412.3.Id1ff21470f08f427aedd0a6535dcd83ccc56b278@changeid Signed-off-by: Ulf Hansson --- drivers/mmc/host/bcm2835.c | 1 + drivers/mmc/host/cavium-octeon.c | 1 + drivers/mmc/host/dw_mmc-zx.c | 1 + drivers/mmc/host/meson-gx-mmc.c | 1 + drivers/mmc/host/renesas_sdhi_internal_dmac.c | 1 + drivers/mmc/host/renesas_sdhi_sys_dmac.c | 1 + drivers/mmc/host/sdhci-cadence.c | 1 + drivers/mmc/host/sdhci-xenon.c | 1 + 8 files changed, 8 insertions(+) diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c index 35320bc9dc02..8c2361e66277 100644 --- a/drivers/mmc/host/bcm2835.c +++ b/drivers/mmc/host/bcm2835.c @@ -1474,6 +1474,7 @@ static struct platform_driver bcm2835_driver = { .remove = bcm2835_remove, .driver = { .name = "sdhost-bcm2835", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = bcm2835_match, }, }; diff --git a/drivers/mmc/host/cavium-octeon.c b/drivers/mmc/host/cavium-octeon.c index e299cdd1e619..2c4b2df52adb 100644 --- a/drivers/mmc/host/cavium-octeon.c +++ b/drivers/mmc/host/cavium-octeon.c @@ -327,6 +327,7 @@ static struct platform_driver octeon_mmc_driver = { .remove = octeon_mmc_remove, .driver = { .name = KBUILD_MODNAME, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = octeon_mmc_match, }, }; diff --git a/drivers/mmc/host/dw_mmc-zx.c b/drivers/mmc/host/dw_mmc-zx.c index d9e483432a61..51bcc6332f3a 100644 --- a/drivers/mmc/host/dw_mmc-zx.c +++ b/drivers/mmc/host/dw_mmc-zx.c @@ -222,6 +222,7 @@ static struct platform_driver dw_mci_zx_pltfm_driver = { .remove = dw_mci_pltfm_remove, .driver = { .name = "dwmmc_zx", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = dw_mci_zx_match, .pm = &dw_mci_zx_dev_pm_ops, }, diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index a68b43082f61..4ec41579940a 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -1264,6 +1264,7 @@ static struct platform_driver meson_mmc_driver = { .remove = meson_mmc_remove, .driver = { .name = DRIVER_NAME, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(meson_mmc_of_match), }, }; diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index 8ee6b2b85ec2..fe13e1ea22dc 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -353,6 +353,7 @@ static const struct dev_pm_ops renesas_sdhi_internal_dmac_dev_pm_ops = { static struct platform_driver renesas_internal_dmac_sdhi_driver = { .driver = { .name = "renesas_sdhi_internal_dmac", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &renesas_sdhi_internal_dmac_dev_pm_ops, .of_match_table = renesas_sdhi_internal_dmac_of_match, }, diff --git a/drivers/mmc/host/renesas_sdhi_sys_dmac.c b/drivers/mmc/host/renesas_sdhi_sys_dmac.c index 13ff023fbee9..c5f789675302 100644 --- a/drivers/mmc/host/renesas_sdhi_sys_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_sys_dmac.c @@ -463,6 +463,7 @@ static const struct dev_pm_ops renesas_sdhi_sys_dmac_dev_pm_ops = { static struct platform_driver renesas_sys_dmac_sdhi_driver = { .driver = { .name = "sh_mobile_sdhi", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &renesas_sdhi_sys_dmac_dev_pm_ops, .of_match_table = renesas_sdhi_sys_dmac_of_match, }, diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c index 4d9f7681817c..6f2de54a5987 100644 --- a/drivers/mmc/host/sdhci-cadence.c +++ b/drivers/mmc/host/sdhci-cadence.c @@ -463,6 +463,7 @@ MODULE_DEVICE_TABLE(of, sdhci_cdns_match); static struct platform_driver sdhci_cdns_driver = { .driver = { .name = "sdhci-cdns", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &sdhci_cdns_pm_ops, .of_match_table = sdhci_cdns_match, }, diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c index 4703cd540c7f..24c978de2a3f 100644 --- a/drivers/mmc/host/sdhci-xenon.c +++ b/drivers/mmc/host/sdhci-xenon.c @@ -677,6 +677,7 @@ MODULE_DEVICE_TABLE(of, sdhci_xenon_dt_ids); static struct platform_driver sdhci_xenon_driver = { .driver = { .name = "xenon-sdhci", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = sdhci_xenon_dt_ids, .pm = &sdhci_xenon_dev_pm_ops, }, From a1a489197a07ec1dbf3f6033b84755a74efc65dc Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 3 Sep 2020 16:24:39 -0700 Subject: [PATCH 64/91] mmc: Set PROBE_PREFER_ASYNCHRONOUS for drivers that existed in v4.19 This is like commit 3d3451124f3d ("mmc: sdhci-msm: Prefer asynchronous probe") but applied to a whole pile of drivers. This batch converts the drivers that appeared to be around in the v4.19 timeframe. Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20200903162412.4.I84eb3e0a738635d524c90d1a688087bc295f7c32@changeid Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc-bluefield.c | 1 + drivers/mmc/host/dw_mmc-hi3798cv200.c | 1 + drivers/mmc/host/meson-mx-sdio.c | 1 + drivers/mmc/host/sdhci-of-dwcmshc.c | 1 + drivers/mmc/host/sdhci-omap.c | 1 + 5 files changed, 5 insertions(+) diff --git a/drivers/mmc/host/dw_mmc-bluefield.c b/drivers/mmc/host/dw_mmc-bluefield.c index aa38b1a8017e..10baf122bc15 100644 --- a/drivers/mmc/host/dw_mmc-bluefield.c +++ b/drivers/mmc/host/dw_mmc-bluefield.c @@ -55,6 +55,7 @@ static struct platform_driver dw_mci_bluefield_pltfm_driver = { .remove = dw_mci_pltfm_remove, .driver = { .name = "dwmmc_bluefield", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = dw_mci_bluefield_match, .pm = &dw_mci_pltfm_pmops, }, diff --git a/drivers/mmc/host/dw_mmc-hi3798cv200.c b/drivers/mmc/host/dw_mmc-hi3798cv200.c index 83e1bad0a008..39794f93826f 100644 --- a/drivers/mmc/host/dw_mmc-hi3798cv200.c +++ b/drivers/mmc/host/dw_mmc-hi3798cv200.c @@ -200,6 +200,7 @@ static struct platform_driver dw_mci_hi3798cv200_driver = { .remove = dw_mci_hi3798cv200_remove, .driver = { .name = "dwmmc_hi3798cv200", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = dw_mci_hi3798cv200_match, }, }; diff --git a/drivers/mmc/host/meson-mx-sdio.c b/drivers/mmc/host/meson-mx-sdio.c index 703d5834f9a5..1c5299cd0cbe 100644 --- a/drivers/mmc/host/meson-mx-sdio.c +++ b/drivers/mmc/host/meson-mx-sdio.c @@ -755,6 +755,7 @@ static struct platform_driver meson_mx_mmc_driver = { .remove = meson_mx_mmc_remove, .driver = { .name = "meson-mx-sdio", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(meson_mx_mmc_of_match), }, }; diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index 64ac0dbee95c..4b673792b5a4 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -214,6 +214,7 @@ MODULE_DEVICE_TABLE(of, sdhci_dwcmshc_dt_ids); static struct platform_driver sdhci_dwcmshc_driver = { .driver = { .name = "sdhci-dwcmshc", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = sdhci_dwcmshc_dt_ids, .pm = &dwcmshc_pmops, }, diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c index 1ec74c2d5c17..7893fd3599b6 100644 --- a/drivers/mmc/host/sdhci-omap.c +++ b/drivers/mmc/host/sdhci-omap.c @@ -1297,6 +1297,7 @@ static struct platform_driver sdhci_omap_driver = { .remove = sdhci_omap_remove, .driver = { .name = "sdhci-omap", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &sdhci_omap_dev_pm_ops, .of_match_table = omap_sdhci_match, }, From d86472ae8b20805449c42467417cfc1ff579a76b Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 3 Sep 2020 16:24:40 -0700 Subject: [PATCH 65/91] mmc: Set PROBE_PREFER_ASYNCHRONOUS for drivers that existed in v5.4 This is like commit 3d3451124f3d ("mmc: sdhci-msm: Prefer asynchronous probe") but applied to a whole pile of drivers. This batch converts the drivers that appeared to be around in the v5.4 timeframe. Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20200903162412.5.I2b630c4d40ff4ea61d5b30b8ccfe95890e257100@changeid Signed-off-by: Ulf Hansson --- drivers/mmc/host/alcor.c | 1 + drivers/mmc/host/sdhci-of-aspeed.c | 2 ++ drivers/mmc/host/sdhci-sprd.c | 1 + drivers/mmc/host/sdhci_am654.c | 1 + drivers/mmc/host/uniphier-sd.c | 1 + 5 files changed, 6 insertions(+) diff --git a/drivers/mmc/host/alcor.c b/drivers/mmc/host/alcor.c index 026ca9194ce5..bfb8efeb7eb8 100644 --- a/drivers/mmc/host/alcor.c +++ b/drivers/mmc/host/alcor.c @@ -1178,6 +1178,7 @@ static struct platform_driver alcor_pci_sdmmc_driver = { .id_table = alcor_pci_sdmmc_ids, .driver = { .name = DRV_NAME_ALCOR_PCI_SDMMC, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &alcor_mmc_pm_ops }, }; diff --git a/drivers/mmc/host/sdhci-of-aspeed.c b/drivers/mmc/host/sdhci-of-aspeed.c index a1bcc0f4ba9e..4f008ba3280e 100644 --- a/drivers/mmc/host/sdhci-of-aspeed.c +++ b/drivers/mmc/host/sdhci-of-aspeed.c @@ -240,6 +240,7 @@ static const struct of_device_id aspeed_sdhci_of_match[] = { static struct platform_driver aspeed_sdhci_driver = { .driver = { .name = "sdhci-aspeed", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = aspeed_sdhci_of_match, }, .probe = aspeed_sdhci_probe, @@ -318,6 +319,7 @@ MODULE_DEVICE_TABLE(of, aspeed_sdc_of_match); static struct platform_driver aspeed_sdc_driver = { .driver = { .name = "sd-controller-aspeed", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &sdhci_pltfm_pmops, .of_match_table = aspeed_sdc_of_match, }, diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index bafa2e41c8b6..1efaf602c206 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -787,6 +787,7 @@ static struct platform_driver sdhci_sprd_driver = { .remove = sdhci_sprd_remove, .driver = { .name = "sdhci_sprd_r11", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(sdhci_sprd_of_match), .pm = &sdhci_sprd_pm_ops, }, diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index c5f47197d177..a4c6d9d80e88 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -745,6 +745,7 @@ static int sdhci_am654_remove(struct platform_device *pdev) static struct platform_driver sdhci_am654_driver = { .driver = { .name = "sdhci-am654", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = sdhci_am654_of_match, }, .probe = sdhci_am654_probe, diff --git a/drivers/mmc/host/uniphier-sd.c b/drivers/mmc/host/uniphier-sd.c index 55efd5c53249..3092466a99ab 100644 --- a/drivers/mmc/host/uniphier-sd.c +++ b/drivers/mmc/host/uniphier-sd.c @@ -685,6 +685,7 @@ static struct platform_driver uniphier_sd_driver = { .remove = uniphier_sd_remove, .driver = { .name = "uniphier-sd", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = uniphier_sd_match, }, }; From 31ae403513be3aa464c28a5544ecb2beb20f32c6 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Thu, 3 Sep 2020 16:24:41 -0700 Subject: [PATCH 66/91] mmc: Set PROBE_PREFER_ASYNCHRONOUS for drivers that are newer than 5.4 This is like commit 3d3451124f3d ("mmc: sdhci-msm: Prefer asynchronous probe") but applied to a whole pile of drivers. This batch converts the drivers that appeared to have been added after kernel 5.4. Signed-off-by: Douglas Anderson Acked-by: Lars Povlsen Acked-by: Angelo Dureghello Acked-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20200903162412.6.Ib121debfb18e5f923a3cd38fe9c36aa086c650c5@changeid Signed-off-by: Ulf Hansson --- drivers/mmc/host/meson-mx-sdhc-mmc.c | 1 + drivers/mmc/host/owl-mmc.c | 1 + drivers/mmc/host/sdhci-esdhc-mcf.c | 1 + drivers/mmc/host/sdhci-milbeaut.c | 1 + drivers/mmc/host/sdhci-of-sparx5.c | 1 + 5 files changed, 5 insertions(+) diff --git a/drivers/mmc/host/meson-mx-sdhc-mmc.c b/drivers/mmc/host/meson-mx-sdhc-mmc.c index 53e3f6a4245a..7cd9c0ec2fcf 100644 --- a/drivers/mmc/host/meson-mx-sdhc-mmc.c +++ b/drivers/mmc/host/meson-mx-sdhc-mmc.c @@ -903,6 +903,7 @@ static struct platform_driver meson_mx_sdhc_driver = { .remove = meson_mx_sdhc_remove, .driver = { .name = "meson-mx-sdhc", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(meson_mx_sdhc_of_match), }, }; diff --git a/drivers/mmc/host/owl-mmc.c b/drivers/mmc/host/owl-mmc.c index df43f42855e2..ccf214a89eda 100644 --- a/drivers/mmc/host/owl-mmc.c +++ b/drivers/mmc/host/owl-mmc.c @@ -689,6 +689,7 @@ MODULE_DEVICE_TABLE(of, owl_mmc_of_match); static struct platform_driver owl_mmc_driver = { .driver = { .name = "owl_mmc", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = owl_mmc_of_match, }, .probe = owl_mmc_probe, diff --git a/drivers/mmc/host/sdhci-esdhc-mcf.c b/drivers/mmc/host/sdhci-esdhc-mcf.c index 71bf086a9812..ca7a1690b2a8 100644 --- a/drivers/mmc/host/sdhci-esdhc-mcf.c +++ b/drivers/mmc/host/sdhci-esdhc-mcf.c @@ -509,6 +509,7 @@ static int sdhci_esdhc_mcf_remove(struct platform_device *pdev) static struct platform_driver sdhci_esdhc_mcf_driver = { .driver = { .name = "sdhci-esdhc-mcf", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .probe = sdhci_esdhc_mcf_probe, .remove = sdhci_esdhc_mcf_remove, diff --git a/drivers/mmc/host/sdhci-milbeaut.c b/drivers/mmc/host/sdhci-milbeaut.c index 4e7cc0680f94..148b37ac6564 100644 --- a/drivers/mmc/host/sdhci-milbeaut.c +++ b/drivers/mmc/host/sdhci-milbeaut.c @@ -333,6 +333,7 @@ static int sdhci_milbeaut_remove(struct platform_device *pdev) static struct platform_driver sdhci_milbeaut_driver = { .driver = { .name = "sdhci-milbeaut", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = of_match_ptr(mlb_dt_ids), }, .probe = sdhci_milbeaut_probe, diff --git a/drivers/mmc/host/sdhci-of-sparx5.c b/drivers/mmc/host/sdhci-of-sparx5.c index 747f108a0ace..28e4ee69e100 100644 --- a/drivers/mmc/host/sdhci-of-sparx5.c +++ b/drivers/mmc/host/sdhci-of-sparx5.c @@ -255,6 +255,7 @@ MODULE_DEVICE_TABLE(of, sdhci_sparx5_of_match); static struct platform_driver sdhci_sparx5_driver = { .driver = { .name = "sdhci-sparx5", + .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = sdhci_sparx5_of_match, .pm = &sdhci_pltfm_pmops, }, From 461aea72af0e3aefff0c428f73c75e6b9ce9fcb5 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 8 Sep 2020 16:02:42 +0200 Subject: [PATCH 67/91] mmc: Drop COMPILE_TEST Kconfig option for MMC_S3C MMC_S3C isn't ready yet to be built with COMPILE_TEST, hence drop it. Signed-off-by: Ulf Hansson Link: https://lore.kernel.org/r/20200908140242.743234-1-ulf.hansson@linaro.org Reviewed-by: Krzysztof Kozlowski --- drivers/mmc/host/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index dc646359b4ff..185a2564e623 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -630,7 +630,7 @@ config MMC_SPI config MMC_S3C tristate "Samsung S3C SD/MMC Card Interface support" - depends on ARCH_S3C24XX || COMPILE_TEST + depends on ARCH_S3C24XX depends on S3C24XX_DMAC help This selects a driver for the MCI interface found in From 354f47b699ae209606dcd0b05200cd7f17059e38 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 2 Sep 2020 10:18:11 +0200 Subject: [PATCH 68/91] mmc: tmio: add generic hook to fixup after a completed request Sadly, due to HW bugs, we need a callback to work around issues just before completing the request. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20200902081812.1591-2-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/tmio_mmc.h | 1 + drivers/mmc/host/tmio_mmc_core.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 51b5f388f6d8..9546e542619c 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -179,6 +179,7 @@ struct tmio_mmc_host { int (*write16_hook)(struct tmio_mmc_host *host, int addr); void (*reset)(struct tmio_mmc_host *host); bool (*check_retune)(struct tmio_mmc_host *host); + void (*fixup_request)(struct tmio_mmc_host *host, struct mmc_request *mrq); void (*prepare_hs400_tuning)(struct tmio_mmc_host *host); void (*hs400_downgrade)(struct tmio_mmc_host *host); diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index 0f266cbf82b8..2fce0518632d 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -809,6 +809,9 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host) return; } + if (host->fixup_request) + host->fixup_request(host, mrq); + mmc_request_done(host->mmc, mrq); } From ce6f92c2801e90650106b00666aa37560978e324 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 2 Sep 2020 10:18:12 +0200 Subject: [PATCH 69/91] mmc: renesas_sdhi: support manual calibration Some R-Car Gen3 SoCs need some manual correction of timing parameters after the automatic tuning has finished but before next CMD13 is completed. This patch implements that by this state machine: - introducing a per-SoC correction table if needed - iff such a table exists, the 'fixup_request' callback is populated during probe - iff such a table exists, a runtime flag ('needs_adjust_hs400') is set when HS400 tuning was completed - the callback will check the runtime flag and enable the corrected manual mode if the flag is set and CMD13 is encountered - at the end of the enablement the runtime flag is cleared - iff the configuration flag is set, the manual mode will be disabled when HS400 gets downgraded There also some helper functions added to access the TMPPORT registers. The actual correction table is SoC and instance(!) specific and is added to the quirks struct. Signed-off-by: Takeshi Saito Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20200902081812.1591-3-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi.h | 5 + drivers/mmc/host/renesas_sdhi_core.c | 152 ++++++++++++++++++++++++++- 2 files changed, 155 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h index 14c64caefc64..24958de274c1 100644 --- a/drivers/mmc/host/renesas_sdhi.h +++ b/drivers/mmc/host/renesas_sdhi.h @@ -33,10 +33,13 @@ struct renesas_sdhi_of_data { unsigned short max_segs; }; +#define SDHI_CALIB_TABLE_MAX 32 + struct renesas_sdhi_quirks { bool hs400_disabled; bool hs400_4taps; u32 hs400_bad_taps; + const u8 (*hs400_calib_table)[SDHI_CALIB_TABLE_MAX]; }; struct tmio_mmc_dma { @@ -58,6 +61,8 @@ struct renesas_sdhi { void __iomem *scc_ctl; u32 scc_tappos; u32 scc_tappos_hs400; + const u8 *adjust_hs400_calib_table; + bool needs_adjust_hs400; bool doing_tune; /* Tuning values: 1 for success, 0 for failure */ diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 42eaec40a6d9..d621a4af8e87 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,8 @@ #define SDHI_VER_GEN3_SD 0xcc10 #define SDHI_VER_GEN3_SDMMC 0xcd10 +#define SDHI_GEN3_MMC0_ADDR 0xee140000 + static void renesas_sdhi_sdbuf_width(struct tmio_mmc_host *host, int width) { u32 val; @@ -251,6 +254,11 @@ static int renesas_sdhi_start_signal_voltage_switch(struct mmc_host *mmc, #define SH_MOBILE_SDHI_SCC_RVSREQ 0x00A #define SH_MOBILE_SDHI_SCC_SMPCMP 0x00C #define SH_MOBILE_SDHI_SCC_TMPPORT2 0x00E +#define SH_MOBILE_SDHI_SCC_TMPPORT3 0x014 +#define SH_MOBILE_SDHI_SCC_TMPPORT4 0x016 +#define SH_MOBILE_SDHI_SCC_TMPPORT5 0x018 +#define SH_MOBILE_SDHI_SCC_TMPPORT6 0x01A +#define SH_MOBILE_SDHI_SCC_TMPPORT7 0x01C #define SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN BIT(0) #define SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT 16 @@ -271,6 +279,40 @@ static int renesas_sdhi_start_signal_voltage_switch(struct mmc_host *mmc, #define SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL BIT(4) #define SH_MOBILE_SDHI_SCC_TMPPORT2_HS400EN BIT(31) +/* Definitions for values the SH_MOBILE_SDHI_SCC_TMPPORT4 register */ +#define SH_MOBILE_SDHI_SCC_TMPPORT4_DLL_ACC_START BIT(0) + +/* Definitions for values the SH_MOBILE_SDHI_SCC_TMPPORT5 register */ +#define SH_MOBILE_SDHI_SCC_TMPPORT5_DLL_RW_SEL_R BIT(8) +#define SH_MOBILE_SDHI_SCC_TMPPORT5_DLL_RW_SEL_W (0 << 8) +#define SH_MOBILE_SDHI_SCC_TMPPORT5_DLL_ADR_MASK 0x3F + +/* Definitions for values the SH_MOBILE_SDHI_SCC register */ +#define SH_MOBILE_SDHI_SCC_TMPPORT_DISABLE_WP_CODE 0xa5000000 +#define SH_MOBILE_SDHI_SCC_TMPPORT_CALIB_CODE_MASK 0x1f +#define SH_MOBILE_SDHI_SCC_TMPPORT_MANUAL_MODE BIT(7) + +static const u8 r8a7796_es13_calib_table[2][SDHI_CALIB_TABLE_MAX] = { + { 3, 3, 3, 3, 3, 3, 3, 4, 4, 5, 6, 7, 8, 9, 10, 15, + 16, 16, 16, 16, 16, 16, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25 }, + { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7, 8, 11, + 12, 17, 18, 18, 18, 18, 18, 18, 18, 19, 20, 21, 22, 23, 25, 25 } +}; + +static const u8 r8a77965_calib_table[2][SDHI_CALIB_TABLE_MAX] = { + { 1, 2, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 25, 26, 27, 28, 29, 30, 31 }, + { 2, 3, 4, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 17, 17, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31, 31, 31, 31 } +}; + +static const u8 r8a77990_calib_table[2][SDHI_CALIB_TABLE_MAX] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 1, 2, 3, 3, 4, 4, 4, 5, 5, 6, 8, 9, 10, + 11, 12, 13, 15, 16, 17, 17, 18, 18, 19, 20, 22, 24, 25, 26, 26 } +}; + static inline u32 sd_scc_read32(struct tmio_mmc_host *host, struct renesas_sdhi *priv, int addr) { @@ -377,6 +419,9 @@ static void renesas_sdhi_hs400_complete(struct mmc_host *mmc) sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN | sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); + + if (priv->adjust_hs400_calib_table) + priv->needs_adjust_hs400 = true; } static void renesas_sdhi_reset_scc(struct tmio_mmc_host *host, @@ -407,6 +452,74 @@ static void renesas_sdhi_disable_scc(struct mmc_host *mmc) sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); } +static u32 sd_scc_tmpport_read32(struct tmio_mmc_host *host, + struct renesas_sdhi *priv, u32 addr) +{ + /* read mode */ + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT5, + SH_MOBILE_SDHI_SCC_TMPPORT5_DLL_RW_SEL_R | + (SH_MOBILE_SDHI_SCC_TMPPORT5_DLL_ADR_MASK & addr)); + + /* access start and stop */ + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT4, + SH_MOBILE_SDHI_SCC_TMPPORT4_DLL_ACC_START); + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT4, 0); + + return sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT7); +} + +static void sd_scc_tmpport_write32(struct tmio_mmc_host *host, + struct renesas_sdhi *priv, u32 addr, u32 val) +{ + /* write mode */ + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT5, + SH_MOBILE_SDHI_SCC_TMPPORT5_DLL_RW_SEL_W | + (SH_MOBILE_SDHI_SCC_TMPPORT5_DLL_ADR_MASK & addr)); + + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT6, val); + + /* access start and stop */ + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT4, + SH_MOBILE_SDHI_SCC_TMPPORT4_DLL_ACC_START); + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT4, 0); +} + +static void renesas_sdhi_adjust_hs400_mode_enable(struct tmio_mmc_host *host) +{ + struct renesas_sdhi *priv = host_to_priv(host); + u32 calib_code; + + /* disable write protect */ + sd_scc_tmpport_write32(host, priv, 0x00, + SH_MOBILE_SDHI_SCC_TMPPORT_DISABLE_WP_CODE); + /* read calibration code and adjust */ + calib_code = sd_scc_tmpport_read32(host, priv, 0x26); + calib_code &= SH_MOBILE_SDHI_SCC_TMPPORT_CALIB_CODE_MASK; + + sd_scc_tmpport_write32(host, priv, 0x22, + SH_MOBILE_SDHI_SCC_TMPPORT_MANUAL_MODE | + priv->adjust_hs400_calib_table[calib_code]); + + /* set offset value to TMPPORT3, hardcoded to OFFSET0 (= 0x3) for now */ + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT3, 0x3); + + /* adjustment done, clear flag */ + priv->needs_adjust_hs400 = false; +} + +static void renesas_sdhi_adjust_hs400_mode_disable(struct tmio_mmc_host *host) +{ + struct renesas_sdhi *priv = host_to_priv(host); + + /* disable write protect */ + sd_scc_tmpport_write32(host, priv, 0x00, + SH_MOBILE_SDHI_SCC_TMPPORT_DISABLE_WP_CODE); + /* disable manual calibration */ + sd_scc_tmpport_write32(host, priv, 0x22, 0); + /* clear offset value of TMPPORT3 */ + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT3, 0); +} + static void renesas_sdhi_reset_hs400_mode(struct tmio_mmc_host *host, struct renesas_sdhi *priv) { @@ -424,6 +537,9 @@ static void renesas_sdhi_reset_hs400_mode(struct tmio_mmc_host *host, SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL) & sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2)); + if (priv->adjust_hs400_calib_table) + renesas_sdhi_adjust_hs400_mode_disable(host); + sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN | sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); } @@ -442,6 +558,7 @@ static void renesas_sdhi_reset(struct tmio_mmc_host *host) renesas_sdhi_reset_scc(host, priv); renesas_sdhi_reset_hs400_mode(host, priv); + priv->needs_adjust_hs400 = false; sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN | sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); @@ -717,6 +834,13 @@ static int renesas_sdhi_multi_io_quirk(struct mmc_card *card, return blk_size; } +static void renesas_sdhi_fixup_request(struct tmio_mmc_host *host, struct mmc_request *mrq) +{ + struct renesas_sdhi *priv = host_to_priv(host); + + if (priv->needs_adjust_hs400 && mrq->cmd->opcode == MMC_SEND_STATUS) + renesas_sdhi_adjust_hs400_mode_enable(host); +} static void renesas_sdhi_enable_dma(struct tmio_mmc_host *host, bool enable) { /* Iff regs are 8 byte apart, sdbuf is 64 bit. Otherwise always 32. */ @@ -748,6 +872,21 @@ static const struct renesas_sdhi_quirks sdhi_quirks_bad_taps2367 = { .hs400_bad_taps = BIT(2) | BIT(3) | BIT(6) | BIT(7), }; +static const struct renesas_sdhi_quirks sdhi_quirks_r8a7796_es13 = { + .hs400_4taps = true, + .hs400_bad_taps = BIT(2) | BIT(3) | BIT(6) | BIT(7), + .hs400_calib_table = r8a7796_es13_calib_table, +}; + +static const struct renesas_sdhi_quirks sdhi_quirks_r8a77965 = { + .hs400_bad_taps = BIT(2) | BIT(3) | BIT(6) | BIT(7), + .hs400_calib_table = r8a77965_calib_table, +}; + +static const struct renesas_sdhi_quirks sdhi_quirks_r8a77990 = { + .hs400_calib_table = r8a77990_calib_table, +}; + /* * Note for r8a7796 / r8a774a1: we can't distinguish ES1.1 and 1.2 as of now. * So, we want to treat them equally and only have a match for ES1.2 to enforce @@ -759,10 +898,11 @@ static const struct soc_device_attribute sdhi_quirks_match[] = { { .soc_id = "r8a7795", .revision = "ES2.0", .data = &sdhi_quirks_4tap }, { .soc_id = "r8a7795", .revision = "ES3.*", .data = &sdhi_quirks_bad_taps2367 }, { .soc_id = "r8a7796", .revision = "ES1.[012]", .data = &sdhi_quirks_4tap_nohs400 }, - { .soc_id = "r8a7796", .revision = "ES1.*", .data = &sdhi_quirks_4tap }, + { .soc_id = "r8a7796", .revision = "ES1.*", .data = &sdhi_quirks_r8a7796_es13 }, { .soc_id = "r8a7796", .revision = "ES3.*", .data = &sdhi_quirks_bad_taps1357 }, - { .soc_id = "r8a77965", .data = &sdhi_quirks_bad_taps2367 }, + { .soc_id = "r8a77965", .data = &sdhi_quirks_r8a77965 }, { .soc_id = "r8a77980", .data = &sdhi_quirks_nohs400 }, + { .soc_id = "r8a77990", .data = &sdhi_quirks_r8a77990 }, { /* Sentinel. */ }, }; @@ -919,6 +1059,14 @@ int renesas_sdhi_probe(struct platform_device *pdev, if (ver == SDHI_VER_GEN2_SDR50) mmc_data->flags &= ~TMIO_MMC_HAVE_CBSY; + if (ver == SDHI_VER_GEN3_SDMMC && quirks && quirks->hs400_calib_table) { + host->fixup_request = renesas_sdhi_fixup_request; + priv->adjust_hs400_calib_table = *( + res->start == SDHI_GEN3_MMC0_ADDR ? + quirks->hs400_calib_table : + quirks->hs400_calib_table + 1); + } + ret = tmio_mmc_host_probe(host); if (ret < 0) goto edisclk; From 91ca244bdcb6a0b6ad12c8325e5e9228b9472374 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 9 Sep 2020 19:41:53 +0530 Subject: [PATCH 70/91] mmc: sdhci-msm: Unconditionally call dev_pm_opp_of_remove_table() dev_pm_opp_of_remove_table() doesn't report any errors when it fails to find the OPP table with error -ENODEV (i.e. OPP table not present for the device). And we can call dev_pm_opp_of_remove_table() unconditionally here. Signed-off-by: Viresh Kumar Link: https://lore.kernel.org/r/890ae5601594fca5de104695a682f4b6efbc631b.1599660554.git.viresh.kumar@linaro.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-msm.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 23dacab1a399..3451eb325513 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -263,7 +263,6 @@ struct sdhci_msm_host { unsigned long clk_rate; struct mmc_host *mmc; struct opp_table *opp_table; - bool has_opp_table; bool use_14lpp_dll_reset; bool tuning_done; bool calibration_done; @@ -2302,11 +2301,9 @@ static int sdhci_msm_probe(struct platform_device *pdev) /* OPP table is optional */ ret = dev_pm_opp_of_add_table(&pdev->dev); - if (!ret) { - msm_host->has_opp_table = true; - } else if (ret != -ENODEV) { + if (ret && ret != -ENODEV) { dev_err(&pdev->dev, "Invalid OPP table in Device tree\n"); - goto opp_cleanup; + goto opp_put_clkname; } /* Vote for maximum clock rate for maximum performance */ @@ -2470,8 +2467,8 @@ clk_disable: clk_bulk_disable_unprepare(ARRAY_SIZE(msm_host->bulk_clks), msm_host->bulk_clks); opp_cleanup: - if (msm_host->has_opp_table) - dev_pm_opp_of_remove_table(&pdev->dev); + dev_pm_opp_of_remove_table(&pdev->dev); +opp_put_clkname: dev_pm_opp_put_clkname(msm_host->opp_table); bus_clk_disable: if (!IS_ERR(msm_host->bus_clk)) @@ -2491,8 +2488,7 @@ static int sdhci_msm_remove(struct platform_device *pdev) sdhci_remove_host(host, dead); - if (msm_host->has_opp_table) - dev_pm_opp_of_remove_table(&pdev->dev); + dev_pm_opp_of_remove_table(&pdev->dev); dev_pm_opp_put_clkname(msm_host->opp_table); pm_runtime_get_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); From 878dbe426a564b164e6d25d21d4bc29a02e7fc2c Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 14 Sep 2020 13:28:45 +0200 Subject: [PATCH 71/91] mmc: core: clear 'doing_init_tune' also after failures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reorganize the code, so that the flag is always cleared independently of a good or bad case. Fixes: 97a7d87e96b0 ("mmc: core: add a 'doing_init_tune' flag and a 'mmc_doing_tune' helper") Signed-off-by: Wolfram Sang Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/20200914112845.21855-1-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/mmc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 67e95eba0e82..ff3063ce2acd 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1766,14 +1766,14 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, host->doing_init_tune = 1; err = mmc_hs200_tuning(card); - if (err) - goto free_card; - - err = mmc_select_hs400(card); - if (err) - goto free_card; + if (!err) + err = mmc_select_hs400(card); host->doing_init_tune = 0; + + if (err) + goto free_card; + } else if (!mmc_card_hs400es(card)) { /* Select the desired bus width optionally */ err = mmc_select_bus_width(card); From 7931b2d56ea4f95ed54d578b483f7c0a28c84a70 Mon Sep 17 00:00:00 2001 From: Amit Singh Tomar Date: Fri, 11 Sep 2020 10:54:09 +0530 Subject: [PATCH 72/91] dt-bindings: mmc: owl: add compatible string actions,s700-mmc The commit adds a new SoC specific compatible string "actions,s700-mmc" in combination with more generic string "actions,owl-mmc". Placement order of these strings should abide by the principle of "from most specific to most general". Reviewed-by: Manivannan Sadhasivam Reviewed-by: Rob Herring Signed-off-by: Amit Singh Tomar Link: https://lore.kernel.org/r/1599801849-6071-1-git-send-email-amittomer25@gmail.com Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/owl-mmc.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mmc/owl-mmc.yaml b/Documentation/devicetree/bindings/mmc/owl-mmc.yaml index 1380501fb8f0..5eab25ccf7ae 100644 --- a/Documentation/devicetree/bindings/mmc/owl-mmc.yaml +++ b/Documentation/devicetree/bindings/mmc/owl-mmc.yaml @@ -14,7 +14,11 @@ maintainers: properties: compatible: - const: actions,owl-mmc + oneOf: + - const: actions,owl-mmc + - items: + - const: actions,s700-mmc + - const: actions,owl-mmc reg: maxItems: 1 From 0caf60c4b110b5aea9a0700be277421c1f575041 Mon Sep 17 00:00:00 2001 From: Amey Narkhede Date: Fri, 18 Sep 2020 00:56:25 +0530 Subject: [PATCH 73/91] mmc: mediatek: Drop pointer to mmc_host from msdc_host The MediaTek MMC driver uses pointer to get from private msdc_host structure to the generic mmc_host structure. However mmc_host always precedes msdc_host in memory so compute its address with a subtraction (which is cheaper than a dereference) using mmc_from_priv() and drop the extra pointer. Signed-off-by: Amey Narkhede Link: https://lore.kernel.org/r/20200917192624.548720-1-ameynarkhede03@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/mtk-sd.c | 45 ++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 691c928edab7..a704745e5882 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -397,7 +397,6 @@ struct msdc_delay_phase { struct msdc_host { struct device *dev; const struct mtk_mmc_compatible *dev_comp; - struct mmc_host *mmc; /* mmc structure */ int cmd_rsp; spinlock_t lock; @@ -734,14 +733,15 @@ static void msdc_unprepare_data(struct msdc_host *host, struct mmc_request *mrq) static u64 msdc_timeout_cal(struct msdc_host *host, u64 ns, u64 clks) { + struct mmc_host *mmc = mmc_from_priv(host); u64 timeout, clk_ns; u32 mode = 0; - if (host->mmc->actual_clock == 0) { + if (mmc->actual_clock == 0) { timeout = 0; } else { clk_ns = 1000000000ULL; - do_div(clk_ns, host->mmc->actual_clock); + do_div(clk_ns, mmc->actual_clock); timeout = ns + clk_ns - 1; do_div(timeout, clk_ns); timeout += clks; @@ -802,6 +802,7 @@ static void msdc_ungate_clock(struct msdc_host *host) static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz) { + struct mmc_host *mmc = mmc_from_priv(host); u32 mode; u32 flags; u32 div; @@ -811,7 +812,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz) if (!hz) { dev_dbg(host->dev, "set mclk to 0\n"); host->mclk = 0; - host->mmc->actual_clock = 0; + mmc->actual_clock = 0; sdr_clr_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN); return; } @@ -890,7 +891,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz) while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB)) cpu_relax(); sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_CKPDN); - host->mmc->actual_clock = sclk; + mmc->actual_clock = sclk; host->mclk = hz; host->timing = timing; /* need because clk changed. */ @@ -901,7 +902,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz) * mmc_select_hs400() will drop to 50Mhz and High speed mode, * tune result of hs200/200Mhz is not suitable for 50Mhz */ - if (host->mmc->actual_clock <= 52000000) { + if (mmc->actual_clock <= 52000000) { writel(host->def_tune_para.iocon, host->base + MSDC_IOCON); if (host->top_base) { writel(host->def_tune_para.emmc_top_control, @@ -932,7 +933,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz) sdr_set_field(host->base + tune_reg, MSDC_PAD_TUNE_CMDRRDLY, host->hs400_cmd_int_delay); - dev_dbg(host->dev, "sclk: %d, timing: %d\n", host->mmc->actual_clock, + dev_dbg(host->dev, "sclk: %d, timing: %d\n", mmc->actual_clock, timing); } @@ -967,6 +968,7 @@ static inline u32 msdc_cmd_find_resp(struct msdc_host *host, static inline u32 msdc_cmd_prepare_raw_cmd(struct msdc_host *host, struct mmc_request *mrq, struct mmc_command *cmd) { + struct mmc_host *mmc = mmc_from_priv(host); /* rawcmd : * vol_swt << 30 | auto_cmd << 28 | blklen << 16 | go_irq << 15 | * stop << 14 | rw << 13 | dtype << 11 | rsptyp << 7 | brk << 6 | opcode @@ -993,7 +995,7 @@ static inline u32 msdc_cmd_prepare_raw_cmd(struct msdc_host *host, struct mmc_data *data = cmd->data; if (mmc_op_multi(opcode)) { - if (mmc_card_mmc(host->mmc->card) && mrq->sbc && + if (mmc_card_mmc(mmc->card) && mrq->sbc && !(mrq->sbc->arg & 0xFFFF0000)) rawcmd |= 0x2 << 28; /* AutoCMD23 */ } @@ -1070,9 +1072,10 @@ static int msdc_auto_cmd_done(struct msdc_host *host, int events, */ static void msdc_recheck_sdio_irq(struct msdc_host *host) { + struct mmc_host *mmc = mmc_from_priv(host); u32 reg_int, reg_inten, reg_ps; - if (host->mmc->caps & MMC_CAP_SDIO_IRQ) { + if (mmc->caps & MMC_CAP_SDIO_IRQ) { reg_inten = readl(host->base + MSDC_INTEN); if (reg_inten & MSDC_INTEN_SDIOIRQ) { reg_int = readl(host->base + MSDC_INT); @@ -1080,7 +1083,7 @@ static void msdc_recheck_sdio_irq(struct msdc_host *host) if (!(reg_int & MSDC_INT_SDIOIRQ || reg_ps & MSDC_PS_DATA1)) { __msdc_enable_sdio_irq(host, 0); - sdio_signal_irq(host->mmc); + sdio_signal_irq(mmc); } } } @@ -1113,7 +1116,7 @@ static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq) msdc_unprepare_data(host, mrq); if (host->error) msdc_reset_hw(host); - mmc_request_done(host->mmc, mrq); + mmc_request_done(mmc_from_priv(host), mrq); if (host->dev_comp->recheck_sdio_irq) msdc_recheck_sdio_irq(host); } @@ -1500,6 +1503,7 @@ static void msdc_enable_sdio_irq(struct mmc_host *mmc, int enb) static irqreturn_t msdc_cmdq_irq(struct msdc_host *host, u32 intsts) { + struct mmc_host *mmc = mmc_from_priv(host); int cmd_err = 0, dat_err = 0; if (intsts & MSDC_INT_RSPCRCERR) { @@ -1523,12 +1527,13 @@ static irqreturn_t msdc_cmdq_irq(struct msdc_host *host, u32 intsts) cmd_err, dat_err, intsts); } - return cqhci_irq(host->mmc, 0, cmd_err, dat_err); + return cqhci_irq(mmc, 0, cmd_err, dat_err); } static irqreturn_t msdc_irq(int irq, void *dev_id) { struct msdc_host *host = (struct msdc_host *) dev_id; + struct mmc_host *mmc = mmc_from_priv(host); while (true) { unsigned long flags; @@ -1551,18 +1556,18 @@ static irqreturn_t msdc_irq(int irq, void *dev_id) spin_unlock_irqrestore(&host->lock, flags); if ((events & event_mask) & MSDC_INT_SDIOIRQ) - sdio_signal_irq(host->mmc); + sdio_signal_irq(mmc); if ((events & event_mask) & MSDC_INT_CDSC) { if (host->internal_cd) - mmc_detect_change(host->mmc, msecs_to_jiffies(20)); + mmc_detect_change(mmc, msecs_to_jiffies(20)); events &= ~MSDC_INT_CDSC; } if (!(events & (event_mask & ~MSDC_INT_SDIOIRQ))) break; - if ((host->mmc->caps2 & MMC_CAP2_CQE) && + if ((mmc->caps2 & MMC_CAP2_CQE) && (events & MSDC_INT_CMDQ)) { msdc_cmdq_irq(host, events); /* clear interrupts */ @@ -2456,7 +2461,6 @@ static int msdc_drv_probe(struct platform_device *pdev) host->dev = &pdev->dev; host->dev_comp = of_device_get_match_data(&pdev->dev); - host->mmc = mmc; host->src_clk_freq = clk_get_rate(host->src_clk); /* Set host parameters to mmc */ mmc->ops = &mt_msdc_ops; @@ -2497,7 +2501,7 @@ static int msdc_drv_probe(struct platform_device *pdev) mmc_dev(mmc)->dma_mask = &host->dma_mask; if (mmc->caps2 & MMC_CAP2_CQE) { - host->cq_host = devm_kzalloc(host->mmc->parent, + host->cq_host = devm_kzalloc(mmc->parent, sizeof(*host->cq_host), GFP_KERNEL); if (!host->cq_host) { @@ -2582,7 +2586,7 @@ static int msdc_drv_remove(struct platform_device *pdev) pm_runtime_get_sync(host->dev); platform_set_drvdata(pdev, NULL); - mmc_remove_host(host->mmc); + mmc_remove_host(mmc); msdc_deinit_hw(host); msdc_gate_clock(host); @@ -2594,7 +2598,7 @@ static int msdc_drv_remove(struct platform_device *pdev) dma_free_coherent(&pdev->dev, MAX_BD_NUM * sizeof(struct mt_bdma_desc), host->dma.bd, host->dma.bd_addr); - mmc_free_host(host->mmc); + mmc_free_host(mmc); return 0; } @@ -2629,6 +2633,7 @@ static void msdc_save_reg(struct msdc_host *host) static void msdc_restore_reg(struct msdc_host *host) { + struct mmc_host *mmc = mmc_from_priv(host); u32 tune_reg = host->dev_comp->pad_tune_reg; writel(host->save_para.msdc_cfg, host->base + MSDC_CFG); @@ -2653,7 +2658,7 @@ static void msdc_restore_reg(struct msdc_host *host) writel(host->save_para.pad_tune, host->base + tune_reg); } - if (sdio_irq_claimed(host->mmc)) + if (sdio_irq_claimed(mmc)) __msdc_enable_sdio_irq(host, 1); } From 3439c588c23c7058b184240b11ffe7edd7b8ac7c Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 18 Sep 2020 23:54:46 +0200 Subject: [PATCH 74/91] mmc: core: document mmc_hw_reset() Add documentation for mmc_hw_reset to make sure the intended use case is clear. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20200918215446.65654-1-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/core/core.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 8ccae6452b9c..d42037f0f10d 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2063,6 +2063,16 @@ static void mmc_hw_reset_for_init(struct mmc_host *host) host->ops->hw_reset(host); } +/** + * mmc_hw_reset - reset the card in hardware + * @host: MMC host to which the card is attached + * + * Hard reset the card. This function is only for upper layers, like the + * block layer or card drivers. You cannot use it in host drivers (struct + * mmc_card might be gone then). + * + * Return: 0 on success, -errno on failure + */ int mmc_hw_reset(struct mmc_host *host) { int ret; From 8dae6a249c635cdc637ae07761beef866480ca0e Mon Sep 17 00:00:00 2001 From: Qinglang Miao Date: Mon, 21 Sep 2020 21:10:42 +0800 Subject: [PATCH 75/91] mmc: rtsx_usb_sdmmc: simplify the return expression of sd_change_phase() Simplify the return expression. Signed-off-by: Qinglang Miao Link: https://lore.kernel.org/r/20200921131042.92340-1-miaoqinglang@huawei.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/rtsx_usb_sdmmc.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c index 598f49573f5d..5fe4528e296e 100644 --- a/drivers/mmc/host/rtsx_usb_sdmmc.c +++ b/drivers/mmc/host/rtsx_usb_sdmmc.c @@ -579,7 +579,6 @@ static void sd_normal_rw(struct rtsx_usb_sdmmc *host, static int sd_change_phase(struct rtsx_usb_sdmmc *host, u8 sample_point, int tx) { struct rtsx_ucr *ucr = host->ucr; - int err; dev_dbg(sdmmc_dev(host), "%s: %s sample_point = %d\n", __func__, tx ? "TX" : "RX", sample_point); @@ -601,11 +600,7 @@ static int sd_change_phase(struct rtsx_usb_sdmmc *host, u8 sample_point, int tx) rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, 0); rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_CFG1, SD_ASYNC_FIFO_RST, 0); - err = rtsx_usb_send_cmd(ucr, MODE_C, 100); - if (err) - return err; - - return 0; + return rtsx_usb_send_cmd(ucr, MODE_C, 100); } static inline u32 get_phase_point(u32 phase_map, unsigned int idx) From fbb31330f9b00bf62fe126a1ea118c02389b06f0 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 22 Sep 2020 19:22:53 +0200 Subject: [PATCH 76/91] mmc: renesas_sdhi: drop local flag for tuning The MMC core has now a generic check if some tuning is in progress. Its protected area is a bit larger than the custom one in this driver but we concluded that this works equally well for the intended case. So, drop the local flag and switch to the generic one. Signed-off-by: Wolfram Sang Reviewed-by: Yoshihiro Shimoda Tested-by: Yoshihiro Shimoda Link: https://lore.kernel.org/r/20200922172253.4458-1-wsa@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi.h | 1 - drivers/mmc/host/renesas_sdhi_core.c | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h index 24958de274c1..cb962c7883dc 100644 --- a/drivers/mmc/host/renesas_sdhi.h +++ b/drivers/mmc/host/renesas_sdhi.h @@ -63,7 +63,6 @@ struct renesas_sdhi { u32 scc_tappos_hs400; const u8 *adjust_hs400_calib_table; bool needs_adjust_hs400; - bool doing_tune; /* Tuning values: 1 for success, 0 for failure */ DECLARE_BITMAP(taps, BITS_PER_LONG); diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index d621a4af8e87..20e5eb63caf8 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -581,7 +581,6 @@ static int renesas_sdhi_select_tuning(struct tmio_mmc_host *host) unsigned int taps_size = priv->tap_num * 2, min_tap_row; unsigned long *bitmap; - priv->doing_tune = false; sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSREQ, 0); /* @@ -656,7 +655,6 @@ static int renesas_sdhi_execute_tuning(struct mmc_host *mmc, u32 opcode) return -EINVAL; } - priv->doing_tune = true; bitmap_zero(priv->taps, priv->tap_num * 2); bitmap_zero(priv->smpcmp, priv->tap_num * 2); @@ -765,7 +763,7 @@ static bool renesas_sdhi_check_scc_error(struct tmio_mmc_host *host) !(host->mmc->ios.timing == MMC_TIMING_MMC_HS400 && !use_4tap)) return false; - if (mmc_doing_retune(host->mmc) || priv->doing_tune) + if (mmc_doing_tune(host->mmc)) return false; if (sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL) & From 6b28f2c4da7e196062d84b143294cf6d86f6e02c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 23 Sep 2020 17:37:38 +0200 Subject: [PATCH 77/91] mmc: moxart: remove unneeded check for drvdata The 'struct mmc_host *mmc' comes from drvdata set at the end of probe, so it cannot be NULL. The code already dereferences it few lines before the check with mmc_priv(). This also fixes smatch warning: drivers/mmc/host/moxart-mmc.c:692 moxart_remove() warn: variable dereferenced before check 'mmc' (see line 688) Reported-by: kernel test robot Reported-by: Dan Carpenter Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200923153739.30327-1-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/moxart-mmc.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c index 2bfb376fddc4..f25079ba3bca 100644 --- a/drivers/mmc/host/moxart-mmc.c +++ b/drivers/mmc/host/moxart-mmc.c @@ -689,19 +689,18 @@ static int moxart_remove(struct platform_device *pdev) dev_set_drvdata(&pdev->dev, NULL); - if (mmc) { - if (!IS_ERR(host->dma_chan_tx)) - dma_release_channel(host->dma_chan_tx); - if (!IS_ERR(host->dma_chan_rx)) - dma_release_channel(host->dma_chan_rx); - mmc_remove_host(mmc); - mmc_free_host(mmc); + if (!IS_ERR(host->dma_chan_tx)) + dma_release_channel(host->dma_chan_tx); + if (!IS_ERR(host->dma_chan_rx)) + dma_release_channel(host->dma_chan_rx); + mmc_remove_host(mmc); + mmc_free_host(mmc); + + writel(0, host->base + REG_INTERRUPT_MASK); + writel(0, host->base + REG_POWER_CONTROL); + writel(readl(host->base + REG_CLOCK_CONTROL) | CLK_OFF, + host->base + REG_CLOCK_CONTROL); - writel(0, host->base + REG_INTERRUPT_MASK); - writel(0, host->base + REG_POWER_CONTROL); - writel(readl(host->base + REG_CLOCK_CONTROL) | CLK_OFF, - host->base + REG_CLOCK_CONTROL); - } return 0; } From 0cb231f1e034bfbb3ccbaf759721d136a6847dde Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 23 Sep 2020 17:37:39 +0200 Subject: [PATCH 78/91] mmc: sdhci: fix indentation mistakes Fix inconsistent indenting, reported by Smatch: drivers/mmc/host/sdhci-esdhc-imx.c:1380 sdhci_esdhc_imx_hwinit() warn: inconsistent indenting drivers/mmc/host/sdhci-sprd.c:390 sdhci_sprd_request_done() warn: inconsistent indenting Reported-by: kernel test robot Reported-by: Dan Carpenter Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200923153739.30327-2-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-esdhc-imx.c | 2 +- drivers/mmc/host/sdhci-sprd.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 62b3d4767916..fce8fa7e6b30 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -1377,7 +1377,7 @@ static void sdhci_esdhc_imx_hwinit(struct sdhci_host *host) * response, block the tuning procedure or the first command * after the whole tuning procedure always can't get any response. */ - tmp |= ESDHC_TUNING_CMD_CRC_CHECK_DISABLE; + tmp |= ESDHC_TUNING_CMD_CRC_CHECK_DISABLE; writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL); } else if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) { /* diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index 1efaf602c206..58109c5b53e2 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -387,7 +387,7 @@ static void sdhci_sprd_request_done(struct sdhci_host *host, if (mmc_hsq_finalize_request(host->mmc, mrq)) return; - mmc_request_done(host->mmc, mrq); + mmc_request_done(host->mmc, mrq); } static struct sdhci_ops sdhci_sprd_ops = { @@ -433,7 +433,7 @@ static void sdhci_sprd_request(struct mmc_host *mmc, struct mmc_request *mrq) } static int sdhci_sprd_request_atomic(struct mmc_host *mmc, - struct mmc_request *mrq) + struct mmc_request *mrq) { sdhci_sprd_check_auto_cmd23(mmc, mrq); From 94d4c3cffefc702da2f906bfc68b774659f1c8fc Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 25 Sep 2020 09:25:32 +0200 Subject: [PATCH 79/91] mmc: sdhci-s3c: hide forward declaration of of_device_id behind CONFIG_OF The struct of_device_id is not defined with !CONFIG_OF so its forward declaration should be hidden to as well. This should address clang compile warning: drivers/mmc/host/sdhci-s3c.c:464:34: warning: tentative array definition assumed to have one element Reported-by: kernel test robot Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20200925072532.10272-1-krzk@kernel.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-s3c.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index cb5f87be7535..f48a788a9d3d 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -461,7 +461,9 @@ static int sdhci_s3c_parse_dt(struct device *dev, } #endif +#ifdef CONFIG_OF static const struct of_device_id sdhci_s3c_dt_match[]; +#endif static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data( struct platform_device *pdev) From 3157b035f499e48334be1ec74b297721b82adb4b Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 25 Sep 2020 09:43:23 -0700 Subject: [PATCH 80/91] mmc: host: fix depends for MMC_MESON_GX w/ COMPILE_TEST Fix build errors for meson-gx-mmc.c when CONFIG_COMMON_CLK is not set/enabled. This can happen when COMPILE_TEST is set/enabled. ERROR: modpost: "clk_divider_ops" [drivers/mmc/host/meson-gx-mmc.ko] undefined! ERROR: modpost: "devm_clk_register" [drivers/mmc/host/meson-gx-mmc.ko] undefined! ERROR: modpost: "clk_mux_ops" [drivers/mmc/host/meson-gx-mmc.ko] undefined! ERROR: modpost: "__clk_get_name" [drivers/mmc/host/meson-gx-mmc.ko] undefined! Fixes: 54d8454436a2 ("mmc: host: Enable compile testing of multiple drivers") Signed-off-by: Randy Dunlap Reviewed-by: Krzysztof Kozlowski Reported-by: kernel test robot Link: https://lore.kernel.org/r/20200925164323.29843-1-rdunlap@infradead.org Signed-off-by: Ulf Hansson --- drivers/mmc/host/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 185a2564e623..f0cb7aeabbc4 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -425,6 +425,7 @@ config MMC_SDHCI_IPROC config MMC_MESON_GX tristate "Amlogic S905/GX*/AXG SD/MMC Host Controller support" depends on ARCH_MESON|| COMPILE_TEST + depends on COMMON_CLK help This selects support for the Amlogic SD/MMC Host Controller found on the S905/GX*/AXG family of SoCs. This controller is From 975520fc73809a3a0904f0c67d8640945696e798 Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Sun, 27 Sep 2020 16:23:04 +0800 Subject: [PATCH 81/91] mmc: sdhci-of-esdhc: fix reference clock source selection The bit ESDHC_PERIPHERAL_CLK_SEL to select using peripheral clock or platform clock is not able to be reset by SDHCI_RESET_ALL. So driver needs to initialize it as 1 or 0 once, to override the different value which may be configured in bootloader. Signed-off-by: Yangbo Lu Link: https://lore.kernel.org/r/20200927082304.9232-1-yangbo.lu@nxp.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-esdhc.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 3a3340c9b8c9..0b45eff6fed4 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -1360,13 +1360,19 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host) clk_put(clk); } - if (esdhc->peripheral_clock) { - esdhc_clock_enable(host, false); - val = sdhci_readl(host, ESDHC_DMA_SYSCTL); + esdhc_clock_enable(host, false); + val = sdhci_readl(host, ESDHC_DMA_SYSCTL); + /* + * This bit is not able to be reset by SDHCI_RESET_ALL. Need to + * initialize it as 1 or 0 once, to override the different value + * which may be configured in bootloader. + */ + if (esdhc->peripheral_clock) val |= ESDHC_PERIPHERAL_CLK_SEL; - sdhci_writel(host, val, ESDHC_DMA_SYSCTL); - esdhc_clock_enable(host, true); - } + else + val &= ~ESDHC_PERIPHERAL_CLK_SEL; + sdhci_writel(host, val, ESDHC_DMA_SYSCTL); + esdhc_clock_enable(host, true); } static int esdhc_hs400_prepare_ddr(struct mmc_host *mmc) From 407d0c2cdd12b5e72695686d4097e7f1331a093e Mon Sep 17 00:00:00 2001 From: Faiz Abbas Date: Wed, 23 Sep 2020 16:22:01 +0530 Subject: [PATCH 82/91] dt-bindings: mmc: sdhci-am654: Convert sdhci-am654 controller documentation to json schema Convert sdhci-am654 documentation to yaml format. The new file sdhci-am654.yaml will inherit from mmc-controller.yaml. Signed-off-by: Faiz Abbas Link: https://lore.kernel.org/r/20200923105206.7988-2-faiz_abbas@ti.com Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/sdhci-am654.txt | 65 ------- .../devicetree/bindings/mmc/sdhci-am654.yaml | 175 ++++++++++++++++++ 2 files changed, 175 insertions(+), 65 deletions(-) delete mode 100644 Documentation/devicetree/bindings/mmc/sdhci-am654.txt create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-am654.yaml diff --git a/Documentation/devicetree/bindings/mmc/sdhci-am654.txt b/Documentation/devicetree/bindings/mmc/sdhci-am654.txt deleted file mode 100644 index b49cbfdd679f..000000000000 --- a/Documentation/devicetree/bindings/mmc/sdhci-am654.txt +++ /dev/null @@ -1,65 +0,0 @@ -Device Tree Bindings for the SDHCI Controllers present on TI's AM654 SOCs - -The bindings follow the mmc[1], clock[2] and interrupt[3] bindings. -Only deviations are documented here. - - [1] Documentation/devicetree/bindings/mmc/mmc.txt - [2] Documentation/devicetree/bindings/clock/clock-bindings.txt - [3] Documentation/devicetree/bindings/interrupt-controller/interrupts.txt - -Required Properties: - - compatible: should be one of: - "ti,am654-sdhci-5.1": SDHCI on AM654 device. - "ti,j721e-sdhci-8bit": 8 bit SDHCI on J721E device. - "ti,j721e-sdhci-4bit": 4 bit SDHCI on J721E device. - "ti,j7200-sdhci-8bit": 8 bit SDHCI on J7200 device. - "ti,j7200-sdhci-4bit": 4 bit SDHCI on J7200 device. - - reg: Must be two entries. - - The first should be the sdhci register space - - The second should the subsystem/phy register space - - clocks: Handles to the clock inputs. - - clock-names: Tuple including "clk_xin" and "clk_ahb" - - interrupts: Interrupt specifiers - Output tap delay for each speed mode: - - ti,otap-del-sel-legacy - - ti,otap-del-sel-mmc-hs - - ti,otap-del-sel-sd-hs - - ti,otap-del-sel-sdr12 - - ti,otap-del-sel-sdr25 - - ti,otap-del-sel-sdr50 - - ti,otap-del-sel-sdr104 - - ti,otap-del-sel-ddr50 - - ti,otap-del-sel-ddr52 - - ti,otap-del-sel-hs200 - - ti,otap-del-sel-hs400 - These bindings must be provided otherwise the driver will disable the - corresponding speed mode (i.e. all nodes must provide at least -legacy) - -Optional Properties (Required for ti,am654-sdhci-5.1, - ti,j721e-sdhci-8bit, - ti,j7200-sdhci-8bit): - - ti,trm-icp: DLL trim select - - ti,driver-strength-ohm: driver strength in ohms. - Valid values are 33, 40, 50, 66 and 100 ohms. -Optional Properties: - - ti,strobe-sel: strobe select delay for HS400 speed mode. Default value: 0x0. - - ti,clkbuf-sel: Clock Delay Buffer Select - -Example: - - sdhci0: sdhci@4f80000 { - compatible = "ti,am654-sdhci-5.1"; - reg = <0x0 0x4f80000 0x0 0x260>, <0x0 0x4f90000 0x0 0x134>; - power-domains = <&k3_pds 47>; - clocks = <&k3_clks 47 0>, <&k3_clks 47 1>; - clock-names = "clk_ahb", "clk_xin"; - interrupts = ; - sdhci-caps-mask = <0x80000007 0x0>; - mmc-ddr-1_8v; - ti,otap-del-sel-legacy = <0x0>; - ti,otap-del-sel-mmc-hs = <0x0>; - ti,otap-del-sel-ddr52 = <0x5>; - ti,otap-del-sel-hs200 = <0x5>; - ti,otap-del-sel-hs400 = <0x0>; - ti,trm-icp = <0x8>; - }; diff --git a/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml b/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml new file mode 100644 index 000000000000..c222e057eca9 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml @@ -0,0 +1,175 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/ +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/mmc/sdhci-am654.yaml#" +$schema : "http://devicetree.org/meta-schemas/core.yaml#" + +title: TI AM654 MMC Controller + +maintainers: + - Ulf Hansson + +allOf: + - $ref: mmc-controller.yaml# + +properties: + compatible: + enum: + - ti,am654-sdhci-5.1 + - ti,j721e-sdhci-8bit + - ti,j721e-sdhci-4bit + - ti,j7200-sdhci-8bit + - ti,j721e-sdhci-4bit + + reg: + maxItems: 2 + + interrupts: + maxItems: 1 + + power-domains: + maxItems: 1 + + clocks: + minItems: 1 + maxItems: 2 + description: Handles to input clocks + + clock-names: + minItems: 1 + maxItems: 2 + items: + - const: clk_ahb + - const: clk_xin + + # PHY output tap delays: + # Used to delay the data valid window and align it to the sampling clock. + # Binding needs to be provided for each supported speed mode otherwise the + # corresponding mode will be disabled. + + ti,otap-del-sel-legacy: + description: Output tap delay for SD/MMC legacy timing + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 0xf + + ti,otap-del-sel-mmc-hs: + description: Output tap delay for MMC high speed timing + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 0xf + + ti,otap-del-sel-sd-hs: + description: Output tap delay for SD high speed timing + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 0xf + + ti,otap-del-sel-sdr12: + description: Output tap delay for SD UHS SDR12 timing + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 0xf + + ti,otap-del-sel-sdr25: + description: Output tap delay for SD UHS SDR25 timing + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 0xf + + ti,otap-del-sel-sdr50: + description: Output tap delay for SD UHS SDR50 timing + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 0xf + + ti,otap-del-sel-sdr104: + description: Output tap delay for SD UHS SDR104 timing + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 0xf + + ti,otap-del-sel-ddr50: + description: Output tap delay for SD UHS DDR50 timing + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 0xf + + ti,otap-del-sel-ddr52: + description: Output tap delay for eMMC DDR52 timing + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 0xf + + ti,otap-del-sel-hs200: + description: Output tap delay for eMMC HS200 timing + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 0xf + + ti,otap-del-sel-hs400: + description: Output tap delay for eMMC HS400 timing + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 0xf + + ti,trm-icp: + description: DLL trim select + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 0xf + + ti,driver-strength-ohm: + description: DLL drive strength in ohms + $ref: "/schemas/types.yaml#/definitions/uint32" + oneOf: + - enum: + - 33 + - 40 + - 50 + - 66 + - 100 + + ti,strobe-sel: + description: strobe select delay for HS400 speed mode. + $ref: "/schemas/types.yaml#/definitions/uint32" + + ti,clkbuf-sel: + description: Clock Delay Buffer Select + $ref: "/schemas/types.yaml#/definitions/uint32" + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - ti,otap-del-sel-legacy + +examples: + - | + #include + #include + + bus { + #address-cells = <2>; + #size-cells = <2>; + + mmc0: mmc@4f80000 { + compatible = "ti,am654-sdhci-5.1"; + reg = <0x0 0x4f80000 0x0 0x260>, <0x0 0x4f90000 0x0 0x134>; + power-domains = <&k3_pds 47>; + clocks = <&k3_clks 47 0>, <&k3_clks 47 1>; + clock-names = "clk_ahb", "clk_xin"; + interrupts = ; + sdhci-caps-mask = <0x80000007 0x0>; + mmc-ddr-1_8v; + ti,otap-del-sel-legacy = <0x0>; + ti,otap-del-sel-mmc-hs = <0x0>; + ti,otap-del-sel-ddr52 = <0x5>; + ti,otap-del-sel-hs200 = <0x5>; + ti,otap-del-sel-hs400 = <0x0>; + ti,trm-icp = <0x8>; + }; + }; From b140954c5f5f6a595d9f474572a408caff558fa5 Mon Sep 17 00:00:00 2001 From: Faiz Abbas Date: Wed, 23 Sep 2020 16:22:02 +0530 Subject: [PATCH 83/91] dt-bindings: mmc: sdhci-am654: Add documentation for input tap delay Add documentation for input tap delay bindings. Signed-off-by: Faiz Abbas Link: https://lore.kernel.org/r/20200923105206.7988-3-faiz_abbas@ti.com Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/sdhci-am654.yaml | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml b/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml index c222e057eca9..ac79f3adf20b 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml +++ b/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml @@ -114,6 +114,46 @@ properties: minimum: 0 maximum: 0xf + # PHY input tap delays: + # Used to delay the data valid window and align it to the sampling clock for + # modes that don't support tuning + + ti,itap-del-sel-legacy: + description: Input tap delay for SD/MMC legacy timing + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 0x1f + + ti,itap-del-sel-mmc-hs: + description: Input tap delay for MMC high speed timing + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 0x1f + + ti,itap-del-sel-sd-hs: + description: Input tap delay for SD high speed timing + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 0x1f + + ti,itap-del-sel-sdr12: + description: Input tap delay for SD UHS SDR12 timing + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 0x1f + + ti,itap-del-sel-sdr25: + description: Input tap delay for SD UHS SDR25 timing + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 0x1f + + ti,itap-del-sel-ddr52: + description: Input tap delay for MMC DDR52 timing + $ref: "/schemas/types.yaml#/definitions/uint32" + minimum: 0 + maximum: 0x1f + ti,trm-icp: description: DLL trim select $ref: "/schemas/types.yaml#/definitions/uint32" @@ -170,6 +210,9 @@ examples: ti,otap-del-sel-ddr52 = <0x5>; ti,otap-del-sel-hs200 = <0x5>; ti,otap-del-sel-hs400 = <0x0>; + ti,itap-del-sel-legacy = <0x10>; + ti,itap-del-sel-mmc-hs = <0xa>; + ti,itap-del-sel-ddr52 = <0x3>; ti,trm-icp = <0x8>; }; }; From 1e753dbb9ce824fc490c0c3757c4f39df72dc28b Mon Sep 17 00:00:00 2001 From: Faiz Abbas Date: Wed, 23 Sep 2020 16:22:03 +0530 Subject: [PATCH 84/91] mmc: sdhci_am654: Fix hard coded otap delay array size Change hard coded array size value to depend on struct timing_data array size. Signed-off-by: Faiz Abbas Link: https://lore.kernel.org/r/20200923105206.7988-4-faiz_abbas@ti.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci_am654.c | 44 +++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index a4c6d9d80e88..9f3347bc3757 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -85,28 +85,6 @@ static struct regmap_config sdhci_am654_regmap_config = { .fast_io = true, }; -struct sdhci_am654_data { - struct regmap *base; - bool legacy_otapdly; - int otap_del_sel[11]; - int clkbuf_sel; - int trm_icp; - int drv_strength; - bool dll_on; - int strb_sel; - u32 flags; -}; - -struct sdhci_am654_driver_data { - const struct sdhci_pltfm_data *pdata; - u32 flags; -#define IOMUX_PRESENT (1 << 0) -#define FREQSEL_2_BIT (1 << 1) -#define STRBSEL_4_BIT (1 << 2) -#define DLL_PRESENT (1 << 3) -#define DLL_CALIB (1 << 4) -}; - struct timing_data { const char *binding; u32 capability; @@ -127,6 +105,28 @@ static const struct timing_data td[] = { [MMC_TIMING_MMC_HS400] = {"ti,otap-del-sel-hs400", MMC_CAP2_HS400}, }; +struct sdhci_am654_data { + struct regmap *base; + bool legacy_otapdly; + int otap_del_sel[ARRAY_SIZE(td)]; + int clkbuf_sel; + int trm_icp; + int drv_strength; + bool dll_on; + int strb_sel; + u32 flags; +}; + +struct sdhci_am654_driver_data { + const struct sdhci_pltfm_data *pdata; + u32 flags; +#define IOMUX_PRESENT (1 << 0) +#define FREQSEL_2_BIT (1 << 1) +#define STRBSEL_4_BIT (1 << 2) +#define DLL_PRESENT (1 << 3) +#define DLL_CALIB (1 << 4) +}; + static void sdhci_am654_setup_dll(struct sdhci_host *host, unsigned int clock) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); From a0a62497f6aac0f9ba25e7befb334046c98fdf92 Mon Sep 17 00:00:00 2001 From: Faiz Abbas Date: Wed, 23 Sep 2020 16:22:04 +0530 Subject: [PATCH 85/91] mmc: sdhci_am654: Add support for input tap delay DLL need only be enabled for speed modes and clock frequencies at or above 50 MHz. For speed modes that don't enable the DLL, we need to configure a static input delay value. This involves reading an optional itap-del-sel-* value from the device tree and configuring it for the appropriate speed mode. With this addition, make sure that DLL is always switched off at the beginning of the set_clock() call to simplify configuration. This also removes the need for the dll_on member in struct sdhci_am654_data. Signed-off-by: Faiz Abbas Link: https://lore.kernel.org/r/20200923105206.7988-5-faiz_abbas@ti.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci_am654.c | 114 ++++++++++++++++++++++++--------- 1 file changed, 84 insertions(+), 30 deletions(-) diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index 9f3347bc3757..1213b711e60a 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -66,6 +66,14 @@ #define RETRIM_MASK BIT(RETRIM_SHIFT) #define SELDLYTXCLK_SHIFT 17 #define SELDLYTXCLK_MASK BIT(SELDLYTXCLK_SHIFT) +#define SELDLYRXCLK_SHIFT 16 +#define SELDLYRXCLK_MASK BIT(SELDLYRXCLK_SHIFT) +#define ITAPDLYSEL_SHIFT 0 +#define ITAPDLYSEL_MASK GENMASK(4, 0) +#define ITAPDLYENA_SHIFT 8 +#define ITAPDLYENA_MASK BIT(ITAPDLYENA_SHIFT) +#define ITAPCHGWIN_SHIFT 9 +#define ITAPCHGWIN_MASK BIT(ITAPCHGWIN_SHIFT) #define DRIVER_STRENGTH_50_OHM 0x0 #define DRIVER_STRENGTH_33_OHM 0x1 @@ -73,7 +81,7 @@ #define DRIVER_STRENGTH_100_OHM 0x3 #define DRIVER_STRENGTH_40_OHM 0x4 -#define CLOCK_TOO_SLOW_HZ 400000 +#define CLOCK_TOO_SLOW_HZ 50000000 /* Command Queue Host Controller Interface Base address */ #define SDHCI_AM654_CQE_BASE_ADDR 0x200 @@ -86,33 +94,55 @@ static struct regmap_config sdhci_am654_regmap_config = { }; struct timing_data { - const char *binding; + const char *otap_binding; + const char *itap_binding; u32 capability; }; static const struct timing_data td[] = { - [MMC_TIMING_LEGACY] = {"ti,otap-del-sel-legacy", 0}, - [MMC_TIMING_MMC_HS] = {"ti,otap-del-sel-mmc-hs", MMC_CAP_MMC_HIGHSPEED}, - [MMC_TIMING_SD_HS] = {"ti,otap-del-sel-sd-hs", MMC_CAP_SD_HIGHSPEED}, - [MMC_TIMING_UHS_SDR12] = {"ti,otap-del-sel-sdr12", MMC_CAP_UHS_SDR12}, - [MMC_TIMING_UHS_SDR25] = {"ti,otap-del-sel-sdr25", MMC_CAP_UHS_SDR25}, - [MMC_TIMING_UHS_SDR50] = {"ti,otap-del-sel-sdr50", MMC_CAP_UHS_SDR50}, - [MMC_TIMING_UHS_SDR104] = {"ti,otap-del-sel-sdr104", + [MMC_TIMING_LEGACY] = {"ti,otap-del-sel-legacy", + "ti,itap-del-sel-legacy", + 0}, + [MMC_TIMING_MMC_HS] = {"ti,otap-del-sel-mmc-hs", + "ti,itap-del-sel-mmc-hs", + MMC_CAP_MMC_HIGHSPEED}, + [MMC_TIMING_SD_HS] = {"ti,otap-del-sel-sd-hs", + "ti,itap-del-sel-sd-hs", + MMC_CAP_SD_HIGHSPEED}, + [MMC_TIMING_UHS_SDR12] = {"ti,otap-del-sel-sdr12", + "ti,itap-del-sel-sdr12", + MMC_CAP_UHS_SDR12}, + [MMC_TIMING_UHS_SDR25] = {"ti,otap-del-sel-sdr25", + "ti,itap-del-sel-sdr25", + MMC_CAP_UHS_SDR25}, + [MMC_TIMING_UHS_SDR50] = {"ti,otap-del-sel-sdr50", + NULL, + MMC_CAP_UHS_SDR50}, + [MMC_TIMING_UHS_SDR104] = {"ti,otap-del-sel-sdr104", + NULL, MMC_CAP_UHS_SDR104}, - [MMC_TIMING_UHS_DDR50] = {"ti,otap-del-sel-ddr50", MMC_CAP_UHS_DDR50}, - [MMC_TIMING_MMC_DDR52] = {"ti,otap-del-sel-ddr52", MMC_CAP_DDR}, - [MMC_TIMING_MMC_HS200] = {"ti,otap-del-sel-hs200", MMC_CAP2_HS200}, - [MMC_TIMING_MMC_HS400] = {"ti,otap-del-sel-hs400", MMC_CAP2_HS400}, + [MMC_TIMING_UHS_DDR50] = {"ti,otap-del-sel-ddr50", + NULL, + MMC_CAP_UHS_DDR50}, + [MMC_TIMING_MMC_DDR52] = {"ti,otap-del-sel-ddr52", + "ti,itap-del-sel-ddr52", + MMC_CAP_DDR}, + [MMC_TIMING_MMC_HS200] = {"ti,otap-del-sel-hs200", + NULL, + MMC_CAP2_HS200}, + [MMC_TIMING_MMC_HS400] = {"ti,otap-del-sel-hs400", + NULL, + MMC_CAP2_HS400}, }; struct sdhci_am654_data { struct regmap *base; bool legacy_otapdly; int otap_del_sel[ARRAY_SIZE(td)]; + int itap_del_sel[ARRAY_SIZE(td)]; int clkbuf_sel; int trm_icp; int drv_strength; - bool dll_on; int strb_sel; u32 flags; }; @@ -135,6 +165,10 @@ static void sdhci_am654_setup_dll(struct sdhci_host *host, unsigned int clock) u32 mask, val; int ret; + /* Disable delay chain mode */ + regmap_update_bits(sdhci_am654->base, PHY_CTRL5, + SELDLYTXCLK_MASK | SELDLYRXCLK_MASK, 0); + if (sdhci_am654->flags & FREQSEL_2_BIT) { switch (clock) { case 200000000: @@ -189,8 +223,32 @@ static void sdhci_am654_setup_dll(struct sdhci_host *host, unsigned int clock) dev_err(mmc_dev(host->mmc), "DLL failed to relock\n"); return; } +} - sdhci_am654->dll_on = true; +static void sdhci_am654_write_itapdly(struct sdhci_am654_data *sdhci_am654, + u32 itapdly) +{ + /* Set ITAPCHGWIN before writing to ITAPDLY */ + regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, + 1 << ITAPCHGWIN_SHIFT); + regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPDLYSEL_MASK, + itapdly << ITAPDLYSEL_SHIFT); + regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0); +} + +static void sdhci_am654_setup_delay_chain(struct sdhci_am654_data *sdhci_am654, + unsigned char timing) +{ + u32 mask, val; + + regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK, 0); + + val = 1 << SELDLYTXCLK_SHIFT | 1 << SELDLYRXCLK_SHIFT; + mask = SELDLYTXCLK_MASK | SELDLYRXCLK_MASK; + regmap_update_bits(sdhci_am654->base, PHY_CTRL5, mask, val); + + sdhci_am654_write_itapdly(sdhci_am654, + sdhci_am654->itap_del_sel[timing]); } static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) @@ -202,11 +260,7 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) u32 otap_del_ena; u32 mask, val; - if (sdhci_am654->dll_on) { - regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK, 0); - - sdhci_am654->dll_on = false; - } + regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK, 0); sdhci_set_clock(host, clock); @@ -234,14 +288,10 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val); - if (timing > MMC_TIMING_UHS_SDR25 && clock > CLOCK_TOO_SLOW_HZ) { - regmap_update_bits(sdhci_am654->base, PHY_CTRL5, - SELDLYTXCLK_MASK, 0); + if (timing > MMC_TIMING_UHS_SDR25 && clock >= CLOCK_TOO_SLOW_HZ) sdhci_am654_setup_dll(host, clock); - } else { - regmap_update_bits(sdhci_am654->base, PHY_CTRL5, - SELDLYTXCLK_MASK, 1 << SELDLYTXCLK_SHIFT); - } + else + sdhci_am654_setup_delay_chain(sdhci_am654, timing); regmap_update_bits(sdhci_am654->base, PHY_CTRL5, CLKBUFSEL_MASK, sdhci_am654->clkbuf_sel); @@ -469,7 +519,7 @@ static int sdhci_am654_get_otap_delay(struct sdhci_host *host, int i; int ret; - ret = device_property_read_u32(dev, td[MMC_TIMING_LEGACY].binding, + ret = device_property_read_u32(dev, td[MMC_TIMING_LEGACY].otap_binding, &sdhci_am654->otap_del_sel[MMC_TIMING_LEGACY]); if (ret) { /* @@ -492,11 +542,11 @@ static int sdhci_am654_get_otap_delay(struct sdhci_host *host, for (i = MMC_TIMING_MMC_HS; i <= MMC_TIMING_MMC_HS400; i++) { - ret = device_property_read_u32(dev, td[i].binding, + ret = device_property_read_u32(dev, td[i].otap_binding, &sdhci_am654->otap_del_sel[i]); if (ret) { dev_dbg(dev, "Couldn't find %s\n", - td[i].binding); + td[i].otap_binding); /* * Remove the corresponding capability * if an otap-del-sel value is not found @@ -506,6 +556,10 @@ static int sdhci_am654_get_otap_delay(struct sdhci_host *host, else host->mmc->caps2 &= ~td[i].capability; } + + if (td[i].itap_binding) + device_property_read_u32(dev, td[i].itap_binding, + &sdhci_am654->itap_del_sel[i]); } return 0; From 13ebeae68ac9830fb8e6e8dfc84f55dba5aab58b Mon Sep 17 00:00:00 2001 From: Faiz Abbas Date: Wed, 23 Sep 2020 16:22:05 +0530 Subject: [PATCH 86/91] mmc: sdhci_am654: Add support for software tuning With the new SW tuning App note[1], a custom tuning algorithm is required for eMMC HS200, HS400 and SD card UHS modes. The algorithm involves running through the 32 possible input tap delay values and sending the appropriate tuning command (CMD19/21) for each of them to get a fail or pass result for each of the values. Typically, the range will have a small contiguous failing window. Considering the tuning range as a circular buffer, the algorithm then sets a final tuned value directly opposite to the failing window. [1] https://www.ti.com/lit/pdf/spract9 Signed-off-by: Faiz Abbas Reviewed-by: Kishon Vijay Abraham I Link: https://lore.kernel.org/r/20200923105206.7988-6-faiz_abbas@ti.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci_am654.c | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index 1213b711e60a..5af7638ad606 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -396,7 +396,46 @@ static u32 sdhci_am654_cqhci_irq(struct sdhci_host *host, u32 intmask) return 0; } +#define ITAP_MAX 32 +static int sdhci_am654_platform_execute_tuning(struct sdhci_host *host, + u32 opcode) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); + int cur_val, prev_val = 1, fail_len = 0, pass_window = 0, pass_len; + u32 itap; + + /* Enable ITAPDLY */ + regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPDLYENA_MASK, + 1 << ITAPDLYENA_SHIFT); + + for (itap = 0; itap < ITAP_MAX; itap++) { + sdhci_am654_write_itapdly(sdhci_am654, itap); + + cur_val = !mmc_send_tuning(host->mmc, opcode, NULL); + if (cur_val && !prev_val) + pass_window = itap; + + if (!cur_val) + fail_len++; + + prev_val = cur_val; + } + /* + * Having determined the length of the failing window and start of + * the passing window calculate the length of the passing window and + * set the final value halfway through it considering the range as a + * circular buffer + */ + pass_len = ITAP_MAX - fail_len; + itap = (pass_window + (pass_len >> 1)) % ITAP_MAX; + sdhci_am654_write_itapdly(sdhci_am654, itap); + + return 0; +} + static struct sdhci_ops sdhci_am654_ops = { + .platform_execute_tuning = sdhci_am654_platform_execute_tuning, .get_max_clock = sdhci_pltfm_clk_get_max_clock, .get_timeout_clock = sdhci_pltfm_clk_get_max_clock, .set_uhs_signaling = sdhci_set_uhs_signaling, @@ -426,6 +465,7 @@ static const struct sdhci_am654_driver_data sdhci_am654_drvdata = { }; static struct sdhci_ops sdhci_j721e_8bit_ops = { + .platform_execute_tuning = sdhci_am654_platform_execute_tuning, .get_max_clock = sdhci_pltfm_clk_get_max_clock, .get_timeout_clock = sdhci_pltfm_clk_get_max_clock, .set_uhs_signaling = sdhci_set_uhs_signaling, @@ -449,6 +489,7 @@ static const struct sdhci_am654_driver_data sdhci_j721e_8bit_drvdata = { }; static struct sdhci_ops sdhci_j721e_4bit_ops = { + .platform_execute_tuning = sdhci_am654_platform_execute_tuning, .get_max_clock = sdhci_pltfm_clk_get_max_clock, .get_timeout_clock = sdhci_pltfm_clk_get_max_clock, .set_uhs_signaling = sdhci_set_uhs_signaling, From 764384d0640376049d1a5c8789ce1c4564c76969 Mon Sep 17 00:00:00 2001 From: Faiz Abbas Date: Wed, 23 Sep 2020 16:22:06 +0530 Subject: [PATCH 87/91] mmc: sdhci_am654: Enable tuning for SDR50 According to the SW tuning App note[1], tuning is required for all UHS speed modes. Tuning for SDR50 is not enabled in Capabilities by default so enable it from the CTL_CFG registers. [1] https://www.ti.com/lit/pdf/spract9 Signed-off-by: Faiz Abbas Link: https://lore.kernel.org/r/20200923105206.7988-7-faiz_abbas@ti.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci_am654.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index 5af7638ad606..2bce962bf7e4 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -19,9 +19,11 @@ /* CTL_CFG Registers */ #define CTL_CFG_2 0x14 +#define CTL_CFG_3 0x18 #define SLOTTYPE_MASK GENMASK(31, 30) #define SLOTTYPE_EMBEDDED BIT(30) +#define TUNINGFORSDR50_MASK BIT(13) /* PHY Registers */ #define PHY_CTRL1 0x100 @@ -646,6 +648,10 @@ static int sdhci_am654_init(struct sdhci_host *host) regmap_update_bits(sdhci_am654->base, CTL_CFG_2, SLOTTYPE_MASK, ctl_cfg_2); + /* Enable tuning for SDR50 */ + regmap_update_bits(sdhci_am654->base, CTL_CFG_3, TUNINGFORSDR50_MASK, + TUNINGFORSDR50_MASK); + ret = sdhci_setup_host(host); if (ret) return ret; From f23cc3ba491af77395cea3f9d51204398729f26b Mon Sep 17 00:00:00 2001 From: Raul E Rangel Date: Mon, 28 Sep 2020 15:59:20 -0600 Subject: [PATCH 88/91] mmc: sdhci-acpi: AMDI0040: Set SDHCI_QUIRK2_PRESET_VALUE_BROKEN This change fixes HS400 tuning for devices with invalid presets. SDHCI presets are not currently used for eMMC HS/HS200/HS400, but are used for DDR52. The HS400 retuning sequence is: HS400->DDR52->HS->HS200->Perform Tuning->HS->HS400 This means that when HS400 tuning happens, we transition through DDR52 for a very brief period. This causes presets to be enabled unintentionally and stay enabled when transitioning back to HS200 or HS400. Some firmware has invalid presets, so we end up with driver strengths that can cause I/O problems. Fixes: 34597a3f60b1 ("mmc: sdhci-acpi: Add support for ACPI HID of AMD Controller with HS400") Signed-off-by: Raul E Rangel Acked-by: Adrian Hunter Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20200928154718.1.Icc21d4b2f354e83e26e57e270dc952f5fe0b0a40@changeid Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-acpi.c | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index fc41d0451f20..54205e3be9e8 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -662,6 +662,43 @@ static int sdhci_acpi_emmc_amd_probe_slot(struct platform_device *pdev, (host->mmc->caps & MMC_CAP_1_8V_DDR)) host->mmc->caps2 = MMC_CAP2_HS400_1_8V; + /* + * There are two types of presets out in the wild: + * 1) Default/broken presets. + * These presets have two sets of problems: + * a) The clock divisor for SDR12, SDR25, and SDR50 is too small. + * This results in clock frequencies that are 2x higher than + * acceptable. i.e., SDR12 = 25 MHz, SDR25 = 50 MHz, SDR50 = + * 100 MHz.x + * b) The HS200 and HS400 driver strengths don't match. + * By default, the SDR104 preset register has a driver strength of + * A, but the (internal) HS400 preset register has a driver + * strength of B. As part of initializing HS400, HS200 tuning + * needs to be performed. Having different driver strengths + * between tuning and operation is wrong. It results in different + * rise/fall times that lead to incorrect sampling. + * 2) Firmware with properly initialized presets. + * These presets have proper clock divisors. i.e., SDR12 => 12MHz, + * SDR25 => 25 MHz, SDR50 => 50 MHz. Additionally the HS200 and + * HS400 preset driver strengths match. + * + * Enabling presets for HS400 doesn't work for the following reasons: + * 1) sdhci_set_ios has a hard coded list of timings that are used + * to determine if presets should be enabled. + * 2) sdhci_get_preset_value is using a non-standard register to + * read out HS400 presets. The AMD controller doesn't support this + * non-standard register. In fact, it doesn't expose the HS400 + * preset register anywhere in the SDHCI memory map. This results + * in reading a garbage value and using the wrong presets. + * + * Since HS400 and HS200 presets must be identical, we could + * instead use the the SDR104 preset register. + * + * If the above issues are resolved we could remove this quirk for + * firmware that that has valid presets (i.e., SDR12 <= 12 MHz). + */ + host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; + host->mmc_host_ops.select_drive_strength = amd_select_drive_strength; host->mmc_host_ops.set_ios = amd_set_ios; host->mmc_host_ops.execute_tuning = amd_sdhci_execute_tuning; From 347f6be11de1940dc915596d17b0f94b03779c77 Mon Sep 17 00:00:00 2001 From: Ben Chuang Date: Mon, 5 Oct 2020 18:55:09 +0800 Subject: [PATCH 89/91] mmc: sdhci-pci-gli: Add CQHCI Support for GL9763E Add CQHCI initialization and implement CQHCI operations for GL9763E. Use bit19 of the register (0x888) to decide whether to disable command queuing. If the bit is set, the command queuing will be disabled. Signed-off-by: Ben Chuang Link: https://lore.kernel.org/r/20201005105509.11343-1-ben.chuanggli@gmail.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pci-gli.c | 150 ++++++++++++++++++++++++++++++- 1 file changed, 148 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c index 5da2b06d84ae..9887485a4134 100644 --- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -14,6 +14,7 @@ #include #include "sdhci.h" #include "sdhci-pci.h" +#include "cqhci.h" /* Genesys Logic extra registers */ #define SDHCI_GLI_9750_WT 0x800 @@ -81,9 +82,16 @@ #define GLI_9763E_VHS_REV_R 0x0 #define GLI_9763E_VHS_REV_M 0x1 #define GLI_9763E_VHS_REV_W 0x2 +#define PCIE_GLI_9763E_MB 0x888 +#define GLI_9763E_MB_CMDQ_OFF BIT(19) #define PCIE_GLI_9763E_SCR 0x8E0 #define GLI_9763E_SCR_AXI_REQ BIT(9) +#define SDHCI_GLI_9763E_CQE_BASE_ADDR 0x200 +#define GLI_9763E_CQE_TRNS_MODE (SDHCI_TRNS_MULTI | \ + SDHCI_TRNS_BLK_CNT_EN | \ + SDHCI_TRNS_DMA) + #define PCI_GLI_9755_WT 0x800 #define PCI_GLI_9755_WT_EN BIT(0) #define GLI_9755_WT_EN_ON 0x1 @@ -578,6 +586,30 @@ static int sdhci_pci_gli_resume(struct sdhci_pci_chip *chip) return sdhci_pci_resume_host(chip); } + +static int sdhci_cqhci_gli_resume(struct sdhci_pci_chip *chip) +{ + struct sdhci_pci_slot *slot = chip->slots[0]; + int ret; + + ret = sdhci_pci_gli_resume(chip); + if (ret) + return ret; + + return cqhci_resume(slot->host->mmc); +} + +static int sdhci_cqhci_gli_suspend(struct sdhci_pci_chip *chip) +{ + struct sdhci_pci_slot *slot = chip->slots[0]; + int ret; + + ret = cqhci_suspend(slot->host->mmc); + if (ret) + return ret; + + return sdhci_suspend_host(slot->host); +} #endif static void gl9763e_hs400_enhanced_strobe(struct mmc_host *mmc, @@ -614,6 +646,110 @@ static void sdhci_set_gl9763e_signaling(struct sdhci_host *host, sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); } +static void sdhci_gl9763e_dumpregs(struct mmc_host *mmc) +{ + sdhci_dumpregs(mmc_priv(mmc)); +} + +static void sdhci_gl9763e_cqe_pre_enable(struct mmc_host *mmc) +{ + struct cqhci_host *cq_host = mmc->cqe_private; + u32 value; + + value = cqhci_readl(cq_host, CQHCI_CFG); + value |= CQHCI_ENABLE; + cqhci_writel(cq_host, value, CQHCI_CFG); +} + +static void sdhci_gl9763e_cqe_enable(struct mmc_host *mmc) +{ + struct sdhci_host *host = mmc_priv(mmc); + + sdhci_writew(host, GLI_9763E_CQE_TRNS_MODE, SDHCI_TRANSFER_MODE); + sdhci_cqe_enable(mmc); +} + +static u32 sdhci_gl9763e_cqhci_irq(struct sdhci_host *host, u32 intmask) +{ + int cmd_error = 0; + int data_error = 0; + + if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) + return intmask; + + cqhci_irq(host->mmc, intmask, cmd_error, data_error); + + return 0; +} + +static void sdhci_gl9763e_cqe_post_disable(struct mmc_host *mmc) +{ + struct sdhci_host *host = mmc_priv(mmc); + struct cqhci_host *cq_host = mmc->cqe_private; + u32 value; + + value = cqhci_readl(cq_host, CQHCI_CFG); + value &= ~CQHCI_ENABLE; + cqhci_writel(cq_host, value, CQHCI_CFG); + sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE); +} + +static const struct cqhci_host_ops sdhci_gl9763e_cqhci_ops = { + .enable = sdhci_gl9763e_cqe_enable, + .disable = sdhci_cqe_disable, + .dumpregs = sdhci_gl9763e_dumpregs, + .pre_enable = sdhci_gl9763e_cqe_pre_enable, + .post_disable = sdhci_gl9763e_cqe_post_disable, +}; + +static int gl9763e_add_host(struct sdhci_pci_slot *slot) +{ + struct device *dev = &slot->chip->pdev->dev; + struct sdhci_host *host = slot->host; + struct cqhci_host *cq_host; + bool dma64; + int ret; + + ret = sdhci_setup_host(host); + if (ret) + return ret; + + cq_host = devm_kzalloc(dev, sizeof(*cq_host), GFP_KERNEL); + if (!cq_host) { + ret = -ENOMEM; + goto cleanup; + } + + cq_host->mmio = host->ioaddr + SDHCI_GLI_9763E_CQE_BASE_ADDR; + cq_host->ops = &sdhci_gl9763e_cqhci_ops; + + dma64 = host->flags & SDHCI_USE_64_BIT_DMA; + if (dma64) + cq_host->caps |= CQHCI_TASK_DESC_SZ_128; + + ret = cqhci_init(cq_host, host->mmc, dma64); + if (ret) + goto cleanup; + + ret = __sdhci_add_host(host); + if (ret) + goto cleanup; + + return 0; + +cleanup: + sdhci_cleanup_host(host); + return ret; +} + +static void sdhci_gl9763e_reset(struct sdhci_host *host, u8 mask) +{ + if ((host->mmc->caps2 & MMC_CAP2_CQE) && (mask & SDHCI_RESET_ALL) && + host->mmc->cqe_private) + cqhci_deactivate(host->mmc); + sdhci_reset(host, mask); +} + static void gli_set_gl9763e(struct sdhci_pci_slot *slot) { struct pci_dev *pdev = slot->chip->pdev; @@ -636,7 +772,9 @@ static void gli_set_gl9763e(struct sdhci_pci_slot *slot) static int gli_probe_slot_gl9763e(struct sdhci_pci_slot *slot) { + struct pci_dev *pdev = slot->chip->pdev; struct sdhci_host *host = slot->host; + u32 value; host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_1_8V_DDR | @@ -646,6 +784,11 @@ static int gli_probe_slot_gl9763e(struct sdhci_pci_slot *slot) MMC_CAP2_HS400_ES | MMC_CAP2_NO_SDIO | MMC_CAP2_NO_SD; + + pci_read_config_dword(pdev, PCIE_GLI_9763E_MB, &value); + if (!(value & GLI_9763E_MB_CMDQ_OFF)) + host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD; + gli_pcie_enable_msi(slot); host->mmc_host_ops.hs400_enhanced_strobe = gl9763e_hs400_enhanced_strobe; @@ -699,9 +842,10 @@ static const struct sdhci_ops sdhci_gl9763e_ops = { .set_clock = sdhci_set_clock, .enable_dma = sdhci_pci_enable_dma, .set_bus_width = sdhci_set_bus_width, - .reset = sdhci_reset, + .reset = sdhci_gl9763e_reset, .set_uhs_signaling = sdhci_set_gl9763e_signaling, .voltage_switch = sdhci_gli_voltage_switch, + .irq = sdhci_gl9763e_cqhci_irq, }; const struct sdhci_pci_fixes sdhci_gl9763e = { @@ -709,6 +853,8 @@ const struct sdhci_pci_fixes sdhci_gl9763e = { .probe_slot = gli_probe_slot_gl9763e, .ops = &sdhci_gl9763e_ops, #ifdef CONFIG_PM_SLEEP - .resume = sdhci_pci_gli_resume, + .resume = sdhci_cqhci_gli_resume, + .suspend = sdhci_cqhci_gli_suspend, #endif + .add_host = gl9763e_add_host, }; From db1af1e9712920f47b5dc6a995fca3eec05ea85e Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 8 Oct 2020 11:25:33 +0200 Subject: [PATCH 90/91] mmc: renesas_sdhi: workaround a regression when reinserting SD cards After the conversions of the reset routines, re-inserting SD cards didn't work anymore. Apply this temporary workaround to have working SD cards during the merge window. The issue will be fixed properly until the final release. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20201008092533.76588-1-wsa+renesas@sang-engineering.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 20e5eb63caf8..414314151d0a 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -572,6 +572,17 @@ static void renesas_sdhi_reset(struct tmio_mmc_host *host) TMIO_MASK_INIT_RCAR2); } +/* + * This is a temporary workaround! This driver used 'hw_reset' wrongly and the + * fix for that showed a regression. So, we mimic the old behaviour until the + * proper solution is found. + */ +static void renesas_sdhi_hw_reset(struct mmc_host *mmc) +{ + struct tmio_mmc_host *host = mmc_priv(mmc); + renesas_sdhi_reset(host); +} + #define SH_MOBILE_SDHI_MIN_TAP_ROW 3 static int renesas_sdhi_select_tuning(struct tmio_mmc_host *host) @@ -1009,6 +1020,8 @@ int renesas_sdhi_probe(struct platform_device *pdev, if (of_data && of_data->scc_offset) { priv->scc_ctl = host->ctl + of_data->scc_offset; host->reset = renesas_sdhi_reset; + host->ops.hw_reset = renesas_sdhi_hw_reset; + host->mmc->caps |= MMC_CAP_HW_RESET; } } From 1e23400f1a7342a2805cc647e6314cd12bfb5526 Mon Sep 17 00:00:00 2001 From: Faiz Abbas Date: Thu, 8 Oct 2020 15:31:29 +0530 Subject: [PATCH 91/91] mmc: sdhci_am654: Fix module autoload Add a MODULE_DEVICE_TABLE() entry so that the driver is autoloaded when built as a module. Signed-off-by: Faiz Abbas Link: https://lore.kernel.org/r/20201008100129.13917-1-faiz_abbas@ti.com Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci_am654.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index 2bce962bf7e4..a64ea143d185 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -739,6 +739,7 @@ static const struct of_device_id sdhci_am654_of_match[] = { }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, sdhci_am654_of_match); static int sdhci_am654_probe(struct platform_device *pdev) {