From fdc4e755f6c516e526dd9396b6eb05712c44fb65 Mon Sep 17 00:00:00 2001 From: Kamlesh Gurudasani Date: Wed, 8 May 2019 01:22:29 +0530 Subject: mmc: android-goldfish: Drop pointer to mmc_host from goldfish_mmc_host The driver for android-goldfish uses a pointer to get from the private goldfish_mmc_host structure to the generic mmc_host structure. However the latter is always immediately preceding the former in memory, so compute its address with a subtraction (which is cheaper than a dereference) and drop the superfluous pointer. No functional change intended. Signed-off-by: Kamlesh Gurudasani Signed-off-by: Ulf Hansson --- drivers/mmc/host/android-goldfish.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/mmc/host/android-goldfish.c b/drivers/mmc/host/android-goldfish.c index 61e4e2a213c9..f6334c2a75bb 100644 --- a/drivers/mmc/host/android-goldfish.c +++ b/drivers/mmc/host/android-goldfish.c @@ -113,7 +113,6 @@ struct goldfish_mmc_host { struct mmc_request *mrq; struct mmc_command *cmd; struct mmc_data *data; - struct mmc_host *mmc; struct device *dev; unsigned char id; /* 16xx chips have 2 MMC blocks */ void *virt_base; @@ -175,7 +174,7 @@ goldfish_mmc_start_command(struct goldfish_mmc_host *host, struct mmc_command *c resptype = 3; break; default: - dev_err(mmc_dev(host->mmc), + dev_err(mmc_dev(mmc_from_priv(host)), "Invalid response type: %04x\n", mmc_resp_type(cmd)); break; } @@ -221,8 +220,8 @@ static void goldfish_mmc_xfer_done(struct goldfish_mmc_host *host, data->sg->length); } host->data->bytes_xfered += data->sg->length; - dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_len, - dma_data_dir); + dma_unmap_sg(mmc_dev(mmc_from_priv(host)), data->sg, + host->sg_len, dma_data_dir); } host->data = NULL; @@ -236,7 +235,7 @@ static void goldfish_mmc_xfer_done(struct goldfish_mmc_host *host, if (!data->stop) { host->mrq = NULL; - mmc_request_done(host->mmc, data->mrq); + mmc_request_done(mmc_from_priv(host), data->mrq); return; } @@ -278,7 +277,7 @@ static void goldfish_mmc_cmd_done(struct goldfish_mmc_host *host, if (host->data == NULL || cmd->error) { host->mrq = NULL; - mmc_request_done(host->mmc, cmd->mrq); + mmc_request_done(mmc_from_priv(host), cmd->mrq); } } @@ -313,7 +312,7 @@ static irqreturn_t goldfish_mmc_irq(int irq, void *dev_id) struct mmc_request *mrq = host->mrq; mrq->cmd->error = -ETIMEDOUT; host->mrq = NULL; - mmc_request_done(host->mmc, mrq); + mmc_request_done(mmc_from_priv(host), mrq); } if (end_command) @@ -339,12 +338,13 @@ static irqreturn_t goldfish_mmc_irq(int irq, void *dev_id) u32 state = GOLDFISH_MMC_READ(host, MMC_STATE); pr_info("%s: Card detect now %d\n", __func__, (state & MMC_STATE_INSERTED)); - mmc_detect_change(host->mmc, 0); + mmc_detect_change(mmc_from_priv(host), 0); } if (!end_command && !end_transfer && !state_changed && !cmd_timeout) { status = GOLDFISH_MMC_READ(host, MMC_INT_STATUS); - dev_info(mmc_dev(host->mmc),"spurious irq 0x%04x\n", status); + dev_info(mmc_dev(mmc_from_priv(host)), "spurious irq 0x%04x\n", + status); if (status != 0) { GOLDFISH_MMC_WRITE(host, MMC_INT_STATUS, status); GOLDFISH_MMC_WRITE(host, MMC_INT_ENABLE, 0); @@ -383,7 +383,7 @@ static void goldfish_mmc_prepare_data(struct goldfish_mmc_host *host, dma_data_dir = mmc_get_dma_dir(data); - host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg, + host->sg_len = dma_map_sg(mmc_dev(mmc_from_priv(host)), data->sg, sg_len, dma_data_dir); host->dma_done = 0; host->dma_in_use = 1; @@ -461,7 +461,6 @@ static int goldfish_mmc_probe(struct platform_device *pdev) } host = mmc_priv(mmc); - host->mmc = mmc; pr_err("mmc: Mapping %lX to %lX\n", (long)res->start, (long)res->end); host->reg_base = ioremap(res->start, resource_size(res)); @@ -508,8 +507,7 @@ static int goldfish_mmc_probe(struct platform_device *pdev) ret = device_create_file(&pdev->dev, &dev_attr_cover_switch); if (ret) - dev_warn(mmc_dev(host->mmc), - "Unable to create sysfs attributes\n"); + dev_warn(mmc_dev(mmc), "Unable to create sysfs attributes\n"); GOLDFISH_MMC_WRITE(host, MMC_SET_BUFFER, host->phys_base); GOLDFISH_MMC_WRITE(host, MMC_INT_ENABLE, @@ -525,7 +523,7 @@ err_request_irq_failed: dma_alloc_failed: iounmap(host->reg_base); ioremap_failed: - mmc_free_host(host->mmc); + mmc_free_host(mmc); err_alloc_host_failed: return ret; } @@ -533,14 +531,15 @@ err_alloc_host_failed: static int goldfish_mmc_remove(struct platform_device *pdev) { struct goldfish_mmc_host *host = platform_get_drvdata(pdev); + struct mmc_host *mmc = mmc_from_priv(host); BUG_ON(host == NULL); - mmc_remove_host(host->mmc); + mmc_remove_host(mmc); free_irq(host->irq, host); dma_free_coherent(&pdev->dev, BUFFER_SIZE, host->virt_base, host->phys_base); iounmap(host->reg_base); - mmc_free_host(host->mmc); + mmc_free_host(mmc); return 0; } -- cgit v1.2.3-59-g8ed1b From 7ff213193310ef8d0ee5f04f79d791210787ac2c Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Thu, 11 Apr 2019 00:22:40 +0200 Subject: mmc: tmio: move runtime PM enablement to the driver implementations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both the Renesas and Uniphier implementations perform actions which affect runtime PM before calling into the core tmio_mmc_host_probe() which enabled runtime PM. Move pm_runtime_enable() from the core and tmio_mmc_host_probe() into each drivers probe() so it can be called before any clocks or other resources are switched on. Reported-by: Geert Uytterhoeven Signed-off-by: Niklas Söderlund Acked-by: Wolfram Sang Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 6 ++++++ drivers/mmc/host/tmio_mmc.c | 5 +++++ drivers/mmc/host/tmio_mmc_core.c | 11 +++++++++-- drivers/mmc/host/uniphier-sd.c | 3 +++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 5e9e36ed2107..db73f9f1b186 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -770,6 +770,8 @@ int renesas_sdhi_probe(struct platform_device *pdev, /* All SDHI have SDIO status bits which must be 1 */ mmc_data->flags |= TMIO_MMC_SDIO_STATUS_SETBITS; + pm_runtime_enable(&pdev->dev); + ret = renesas_sdhi_clk_enable(host); if (ret) goto efree; @@ -850,6 +852,8 @@ edisclk: efree: tmio_mmc_host_free(host); + pm_runtime_disable(&pdev->dev); + return ret; } EXPORT_SYMBOL_GPL(renesas_sdhi_probe); @@ -861,6 +865,8 @@ int renesas_sdhi_remove(struct platform_device *pdev) tmio_mmc_host_remove(host); renesas_sdhi_clk_disable(host); + pm_runtime_disable(&pdev->dev); + return 0; } EXPORT_SYMBOL_GPL(renesas_sdhi_remove); diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 93e83ad25976..8539e10784b4 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -172,6 +172,8 @@ static int tmio_mmc_probe(struct platform_device *pdev) host->mmc->f_max = pdata->hclk; host->mmc->f_min = pdata->hclk / 512; + pm_runtime_enable(&pdev->dev); + ret = tmio_mmc_host_probe(host); if (ret) goto host_free; @@ -191,6 +193,7 @@ host_remove: tmio_mmc_host_remove(host); host_free: tmio_mmc_host_free(host); + pm_runtime_disable(&pdev->dev); cell_disable: if (cell->disable) cell->disable(pdev); @@ -207,6 +210,8 @@ static int tmio_mmc_remove(struct platform_device *pdev) if (cell->disable) cell->disable(pdev); + pm_runtime_disable(&pdev->dev); + return 0; } diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index 84cb7d2aacdf..83fd94341113 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -1153,6 +1153,15 @@ void tmio_mmc_host_free(struct tmio_mmc_host *host) } EXPORT_SYMBOL_GPL(tmio_mmc_host_free); +/** + * tmio_mmc_host_probe() - Common probe for all implementations + * @_host: Host to probe + * + * Perform tasks common to all implementations probe functions. + * + * The caller should have called pm_runtime_enable() prior to calling + * the common probe function. + */ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) { struct platform_device *pdev = _host->pdev; @@ -1261,7 +1270,6 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) pm_runtime_set_active(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, 50); pm_runtime_use_autosuspend(&pdev->dev); - pm_runtime_enable(&pdev->dev); ret = mmc_add_host(mmc); if (ret) @@ -1297,7 +1305,6 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host) pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); - pm_runtime_disable(&pdev->dev); } EXPORT_SYMBOL_GPL(tmio_mmc_host_remove); diff --git a/drivers/mmc/host/uniphier-sd.c b/drivers/mmc/host/uniphier-sd.c index 91a2be41edf6..49aad9a79c18 100644 --- a/drivers/mmc/host/uniphier-sd.c +++ b/drivers/mmc/host/uniphier-sd.c @@ -631,6 +631,7 @@ static int uniphier_sd_probe(struct platform_device *pdev) host->clk_disable = uniphier_sd_clk_disable; host->set_clock = uniphier_sd_set_clock; + pm_runtime_enable(&pdev->dev); ret = uniphier_sd_clk_enable(host); if (ret) goto free_host; @@ -652,6 +653,7 @@ static int uniphier_sd_probe(struct platform_device *pdev) free_host: tmio_mmc_host_free(host); + pm_runtime_disable(&pdev->dev); return ret; } @@ -662,6 +664,7 @@ static int uniphier_sd_remove(struct platform_device *pdev) tmio_mmc_host_remove(host); uniphier_sd_clk_disable(host); + pm_runtime_disable(&pdev->dev); return 0; } -- cgit v1.2.3-59-g8ed1b From 754aee559160fe6a9d7debe9f1ad07d060e6ae93 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 20 May 2019 16:36:46 +0200 Subject: mmc: meson-gx-mmc: update with SPDX Licence identifier Signed-off-by: Neil Armstrong Acked-by: Kevin Hilman Signed-off-by: Ulf Hansson --- drivers/mmc/host/meson-gx-mmc.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index 5582561586b4..747d92daf9d7 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Amlogic SD/eMMC driver for the GX/S905 family SoCs * * Copyright (c) 2016 BayLibre, SAS. * Author: Kevin Hilman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * The full GNU General Public License is included in this distribution - * in the file called COPYING. */ #include #include -- cgit v1.2.3-59-g8ed1b From 5a46b6fa0f33c2ca7a8432a0a48e1bf4a71fcc9f Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 27 May 2019 14:43:05 +0200 Subject: dt-bindings: mmc: meson-gx: add dram-access-quirk property On the Amlogic G12A SoC family, (only) the SDIO controller has a bug which makes any DRAM access from the MMC controller fail. Add the amlogic,dram-access-quirk property so signal this particular controller has this bug and needs a quirk to work properly. Reviewed-by: Martin Blumenstingl Signed-off-by: Neil Armstrong Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/amlogic,meson-gx.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/amlogic,meson-gx.txt b/Documentation/devicetree/bindings/mmc/amlogic,meson-gx.txt index 13e70409e8ac..ccc5358db131 100644 --- a/Documentation/devicetree/bindings/mmc/amlogic,meson-gx.txt +++ b/Documentation/devicetree/bindings/mmc/amlogic,meson-gx.txt @@ -22,6 +22,10 @@ Required properties: clock rate requested by the MMC core. - resets : phandle of the internal reset line +Optional properties: +- amlogic,dram-access-quirk: set when controller's internal DMA engine cannot access the + DRAM memory, like on the G12A dedicated SDIO controller. + Example: sd_emmc_a: mmc@70000 { -- cgit v1.2.3-59-g8ed1b From acdc8e71d9bb0bdef66b002f8baf8af3147df00c Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 27 May 2019 14:43:06 +0200 Subject: mmc: meson-gx: add dram-access-quirk On the Amlogic G12A SoC family, (only) the SDIO controller fails to access the data from DRAM, leading to a broken controller. But each MMC controller has 1,5KiB of SRAM after the registers, that can be used as bounce buffer to avoid direct DRAM access from the integrated DMAs (this SRAM may be used by the boot ROM when DRAM is not yet initialized). The quirk is to disable the chained descriptor for this controller, and use this SRAM memory zone as buffer for the bounce buffer fallback mode. The performance hit hasn't been evaluated, but the fix has been tested using a WiFi AP6398S SDIO module, and the iperf3 Bandwidth measurement gave 55.2 Mbits/sec over a 63 Hours long test, with the SDIO ios set as High-Speed at 50MHz clock. It gave 170 Mbits/sec as SDR104 and 200MHz clock. Reviewed-by: Kevin Hilman Tested-by: Guillaume La Roque Signed-off-by: Neil Armstrong Signed-off-by: Ulf Hansson --- drivers/mmc/host/meson-gx-mmc.c | 70 ++++++++++++++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 15 deletions(-) diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index 747d92daf9d7..26f33431120e 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -116,6 +116,9 @@ #define SD_EMMC_TXD 0x94 #define SD_EMMC_LAST_REG SD_EMMC_TXD +#define SD_EMMC_SRAM_DATA_BUF_LEN 1536 +#define SD_EMMC_SRAM_DATA_BUF_OFF 0x200 + #define SD_EMMC_CFG_BLK_SIZE 512 /* internal buffer max: 512 bytes */ #define SD_EMMC_CFG_RESP_TIMEOUT 256 /* in clock cycles */ #define SD_EMMC_CMD_TIMEOUT 1024 /* in ms */ @@ -155,6 +158,8 @@ struct meson_host { unsigned long req_rate; bool ddr; + bool dram_access_quirk; + struct pinctrl *pinctrl; struct pinctrl_state *pins_default; struct pinctrl_state *pins_clk_gate; @@ -219,11 +224,20 @@ static struct mmc_command *meson_mmc_get_next_command(struct mmc_command *cmd) static void meson_mmc_get_transfer_mode(struct mmc_host *mmc, struct mmc_request *mrq) { + struct meson_host *host = mmc_priv(mmc); struct mmc_data *data = mrq->data; struct scatterlist *sg; int i; bool use_desc_chain_mode = true; + /* + * When Controller DMA cannot directly access DDR memory, disable + * support for Chain Mode to directly use the internal SRAM using + * the bounce buffer mode. + */ + if (host->dram_access_quirk) + return; + /* * Broken SDIO with AP6255-based WiFi on Khadas VIM Pro has been * reported. For some strange reason this occurs in descriptor @@ -1036,6 +1050,10 @@ static int meson_mmc_probe(struct platform_device *pdev) host->dev = &pdev->dev; dev_set_drvdata(&pdev->dev, host); + /* The G12A SDIO Controller needs an SRAM bounce buffer */ + host->dram_access_quirk = device_property_read_bool(&pdev->dev, + "amlogic,dram-access-quirk"); + /* Get regulators and the supported OCR mask */ host->vqmmc_enabled = false; ret = mmc_regulator_get_supply(mmc); @@ -1133,9 +1151,16 @@ static int meson_mmc_probe(struct platform_device *pdev) goto err_init_clk; mmc->caps |= MMC_CAP_CMD23; - mmc->max_blk_count = CMD_CFG_LENGTH_MASK; + if (host->dram_access_quirk) { + /* Limit to the available sram memory */ + mmc->max_segs = SD_EMMC_SRAM_DATA_BUF_LEN / mmc->max_blk_size; + mmc->max_blk_count = mmc->max_segs; + } else { + mmc->max_blk_count = CMD_CFG_LENGTH_MASK; + mmc->max_segs = SD_EMMC_DESC_BUF_LEN / + sizeof(struct sd_emmc_desc); + } mmc->max_req_size = mmc->max_blk_count * mmc->max_blk_size; - mmc->max_segs = SD_EMMC_DESC_BUF_LEN / sizeof(struct sd_emmc_desc); mmc->max_seg_size = mmc->max_req_size; /* @@ -1145,15 +1170,27 @@ static int meson_mmc_probe(struct platform_device *pdev) */ mmc->caps2 &= ~MMC_CAP2_HS400; - /* data bounce buffer */ - host->bounce_buf_size = mmc->max_req_size; - host->bounce_buf = - dma_alloc_coherent(host->dev, host->bounce_buf_size, - &host->bounce_dma_addr, GFP_KERNEL); - if (host->bounce_buf == NULL) { - dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n"); - ret = -ENOMEM; - goto err_free_irq; + if (host->dram_access_quirk) { + /* + * The MMC Controller embeds 1,5KiB of internal SRAM + * that can be used to be used as bounce buffer. + * In the case of the G12A SDIO controller, use these + * instead of the DDR memory + */ + host->bounce_buf_size = SD_EMMC_SRAM_DATA_BUF_LEN; + host->bounce_buf = host->regs + SD_EMMC_SRAM_DATA_BUF_OFF; + host->bounce_dma_addr = res->start + SD_EMMC_SRAM_DATA_BUF_OFF; + } else { + /* data bounce buffer */ + host->bounce_buf_size = mmc->max_req_size; + host->bounce_buf = + dma_alloc_coherent(host->dev, host->bounce_buf_size, + &host->bounce_dma_addr, GFP_KERNEL); + if (host->bounce_buf == NULL) { + dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n"); + ret = -ENOMEM; + goto err_free_irq; + } } host->descs = dma_alloc_coherent(host->dev, SD_EMMC_DESC_BUF_LEN, @@ -1170,8 +1207,9 @@ static int meson_mmc_probe(struct platform_device *pdev) return 0; err_bounce_buf: - dma_free_coherent(host->dev, host->bounce_buf_size, - host->bounce_buf, host->bounce_dma_addr); + if (!host->dram_access_quirk) + dma_free_coherent(host->dev, host->bounce_buf_size, + host->bounce_buf, host->bounce_dma_addr); err_free_irq: free_irq(host->irq, host); err_init_clk: @@ -1195,8 +1233,10 @@ static int meson_mmc_remove(struct platform_device *pdev) dma_free_coherent(host->dev, SD_EMMC_DESC_BUF_LEN, host->descs, host->descs_dma_addr); - dma_free_coherent(host->dev, host->bounce_buf_size, - host->bounce_buf, host->bounce_dma_addr); + + if (!host->dram_access_quirk) + dma_free_coherent(host->dev, host->bounce_buf_size, + host->bounce_buf, host->bounce_dma_addr); clk_disable_unprepare(host->mmc_clk); clk_disable_unprepare(host->core_clk); -- cgit v1.2.3-59-g8ed1b From 65f1a0d39c289bb6fc85635528cd36c4b07f560e Mon Sep 17 00:00:00 2001 From: Wang Hai Date: Wed, 15 May 2019 22:37:25 +0800 Subject: memstick: Fix error cleanup path of memstick_init If bus_register fails. On its error handling path, it has cleaned up what it has done. There is no need to call bus_unregister again. Otherwise, if bus_unregister is called, issues such as null-ptr-deref will arise. Syzkaller report this: kobject_add_internal failed for memstick (error: -12 parent: bus) BUG: KASAN: null-ptr-deref in sysfs_remove_file_ns+0x1b/0x40 fs/sysfs/file.c:467 Read of size 8 at addr 0000000000000078 by task syz-executor.0/4460 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0xa9/0x10e lib/dump_stack.c:113 __kasan_report+0x171/0x18d mm/kasan/report.c:321 kasan_report+0xe/0x20 mm/kasan/common.c:614 sysfs_remove_file_ns+0x1b/0x40 fs/sysfs/file.c:467 sysfs_remove_file include/linux/sysfs.h:519 [inline] bus_remove_file+0x6c/0x90 drivers/base/bus.c:145 remove_probe_files drivers/base/bus.c:599 [inline] bus_unregister+0x6e/0x100 drivers/base/bus.c:916 ? 0xffffffffc1590000 memstick_init+0x7a/0x1000 [memstick] do_one_initcall+0xb9/0x3b5 init/main.c:914 do_init_module+0xe0/0x330 kernel/module.c:3468 load_module+0x38eb/0x4270 kernel/module.c:3819 __do_sys_finit_module+0x162/0x190 kernel/module.c:3909 do_syscall_64+0x72/0x2a0 arch/x86/entry/common.c:298 entry_SYSCALL_64_after_hwframe+0x49/0xbe Fixes: baf8532a147d ("memstick: initial commit for Sony MemoryStick support") Reported-by: Hulk Robot Signed-off-by: Wang Hai Signed-off-by: Ulf Hansson --- drivers/memstick/core/memstick.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c index 1246d69ba187..b1564cacd19e 100644 --- a/drivers/memstick/core/memstick.c +++ b/drivers/memstick/core/memstick.c @@ -629,13 +629,18 @@ static int __init memstick_init(void) return -ENOMEM; rc = bus_register(&memstick_bus_type); - if (!rc) - rc = class_register(&memstick_host_class); + if (rc) + goto error_destroy_workqueue; - if (!rc) - return 0; + rc = class_register(&memstick_host_class); + if (rc) + goto error_bus_unregister; + + return 0; +error_bus_unregister: bus_unregister(&memstick_bus_type); +error_destroy_workqueue: destroy_workqueue(workqueue); return rc; -- cgit v1.2.3-59-g8ed1b From 8023cf2634b051ff53739a035a0c1bef3cbb389c Mon Sep 17 00:00:00 2001 From: Faiz Abbas Date: Tue, 28 May 2019 15:29:27 +0530 Subject: mmc: sdhci_am654: Improve whitespace utilisation with regmap_*() calls Line wrapping with the regmap_*() functions is way more conservative than required by the 80 character rule. Expand the function calls out to use less number of lines. Signed-off-by: Faiz Abbas Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci_am654.c | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index 3222ea4d584d..3c32d9fb6e1e 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -88,8 +88,7 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) int ret; if (sdhci_am654->dll_on) { - regmap_update_bits(sdhci_am654->base, PHY_CTRL1, - ENDLL_MASK, 0); + regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK, 0); sdhci_am654->dll_on = false; } @@ -101,8 +100,7 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; val = (1 << OTAPDLYENA_SHIFT) | (sdhci_am654->otap_del_sel << OTAPDLYSEL_SHIFT); - regmap_update_bits(sdhci_am654->base, PHY_CTRL4, - mask, val); + regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val); switch (clock) { case 200000000: sel50 = 0; @@ -120,8 +118,7 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) /* Configure PHY DLL frequency */ mask = SEL50_MASK | SEL100_MASK; val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT); - regmap_update_bits(sdhci_am654->base, PHY_CTRL5, - mask, val); + regmap_update_bits(sdhci_am654->base, PHY_CTRL5, mask, val); /* Configure DLL TRIM */ mask = DLL_TRIM_ICP_MASK; val = sdhci_am654->trm_icp << DLL_TRIM_ICP_SHIFT; @@ -129,20 +126,17 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) /* Configure DLL driver strength */ mask |= DR_TY_MASK; val |= sdhci_am654->drv_strength << DR_TY_SHIFT; - regmap_update_bits(sdhci_am654->base, PHY_CTRL1, - mask, val); + regmap_update_bits(sdhci_am654->base, PHY_CTRL1, mask, val); /* Enable DLL */ - regmap_update_bits(sdhci_am654->base, PHY_CTRL1, - ENDLL_MASK, 0x1 << ENDLL_SHIFT); + regmap_update_bits(sdhci_am654->base, PHY_CTRL1, ENDLL_MASK, + 0x1 << ENDLL_SHIFT); /* * Poll for DLL ready. Use a one second timeout. * Works in all experiments done so far */ - ret = regmap_read_poll_timeout(sdhci_am654->base, - PHY_STAT1, val, - val & DLLRDY_MASK, - 1000, 1000000); - + ret = regmap_read_poll_timeout(sdhci_am654->base, PHY_STAT1, + val, val & DLLRDY_MASK, 1000, + 1000000); sdhci_am654->dll_on = true; } } @@ -208,8 +202,7 @@ static int sdhci_am654_init(struct sdhci_host *host) /* Reset OTAP to default value */ mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; - regmap_update_bits(sdhci_am654->base, PHY_CTRL4, - mask, 0x0); + regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, 0x0); regmap_read(sdhci_am654->base, PHY_STAT1, &val); if (~val & CALDONE_MASK) { @@ -223,15 +216,14 @@ static int sdhci_am654_init(struct sdhci_host *host) } /* Enable pins by setting IO mux to 0 */ - regmap_update_bits(sdhci_am654->base, PHY_CTRL1, - IOMUX_ENABLE_MASK, 0); + regmap_update_bits(sdhci_am654->base, PHY_CTRL1, IOMUX_ENABLE_MASK, 0); /* Set slot type based on SD or eMMC */ if (host->mmc->caps & MMC_CAP_NONREMOVABLE) ctl_cfg_2 = SLOTTYPE_EMBEDDED; - regmap_update_bits(sdhci_am654->base, CTL_CFG_2, - SLOTTYPE_MASK, ctl_cfg_2); + regmap_update_bits(sdhci_am654->base, CTL_CFG_2, SLOTTYPE_MASK, + ctl_cfg_2); return sdhci_add_host(host); } -- cgit v1.2.3-59-g8ed1b From 7e24e28b79b3df4fb1db40f26c46e0a3480eede4 Mon Sep 17 00:00:00 2001 From: Faiz Abbas Date: Tue, 28 May 2019 15:29:28 +0530 Subject: mmc: sdhci_am654: Print error message if the DLL fails to lock Print an error message and return if DLL fails to lock. Signed-off-by: Faiz Abbas Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci_am654.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index 3c32d9fb6e1e..d0b20780dd0f 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -137,6 +137,11 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) ret = regmap_read_poll_timeout(sdhci_am654->base, PHY_STAT1, val, val & DLLRDY_MASK, 1000, 1000000); + if (ret) { + dev_err(mmc_dev(host->mmc), "DLL failed to relock\n"); + return; + } + sdhci_am654->dll_on = true; } } -- cgit v1.2.3-59-g8ed1b From f9b7989859dd005ffcd8aea5a9c862f61cda9cd8 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 29 May 2019 09:23:43 +0200 Subject: dt-bindings: mmc: Add YAML schemas for the generic MMC options The MMC controllers have a bunch of generic options that are needed in a device tree. Add a YAML schemas for those. Reviewed-by: Rob Herring Signed-off-by: Maxime Ripard Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/mmc-controller.yaml | 374 +++++++++++++++++++++ Documentation/devicetree/bindings/mmc/mmc.txt | 178 +--------- 2 files changed, 375 insertions(+), 177 deletions(-) create mode 100644 Documentation/devicetree/bindings/mmc/mmc-controller.yaml diff --git a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml new file mode 100644 index 000000000000..080754e0ef35 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml @@ -0,0 +1,374 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/mmc-controller.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MMC Controller Generic Binding + +maintainers: + - Ulf Hansson + +description: | + These properties are common to multiple MMC host controllers. Any host + that requires the respective functionality should implement them using + these definitions. + +properties: + $nodename: + pattern: "^mmc(@.*)?$" + + "#address-cells": + const: 1 + description: | + The cell is the slot ID if a function subnode is used. + + "#size-cells": + const: 0 + + # Card Detection. + # If none of these properties are supplied, the host native card + # detect will be used. Only one of them should be provided. + + broken-cd: + $ref: /schemas/types.yaml#/definitions/flag + description: + There is no card detection available; polling must be used. + + cd-gpios: + description: + The card detection will be done using the GPIO provided. + + non-removable: + $ref: /schemas/types.yaml#/definitions/flag + description: + Non-removable slot (like eMMC); assume always present. + + # *NOTE* on CD and WP polarity. To use common for all SD/MMC host + # controllers line polarity properties, we have to fix the meaning + # of the "normal" and "inverted" line levels. We choose to follow + # the SDHCI standard, which specifies both those lines as "active + # low." Therefore, using the "cd-inverted" property means, that the + # CD line is active high, i.e. it is high, when a card is + # inserted. Similar logic applies to the "wp-inverted" property. + # + # CD and WP lines can be implemented on the hardware in one of two + # ways: as GPIOs, specified in cd-gpios and wp-gpios properties, or + # as dedicated pins. Polarity of dedicated pins can be specified, + # using *-inverted properties. GPIO polarity can also be specified + # using the GPIO_ACTIVE_LOW flag. This creates an ambiguity in the + # latter case. We choose to use the XOR logic for GPIO CD and WP + # lines. This means, the two properties are "superimposed," for + # example leaving the GPIO_ACTIVE_LOW flag clear and specifying the + # respective *-inverted property property results in a + # double-inversion and actually means the "normal" line polarity is + # in effect. + wp-inverted: + $ref: /schemas/types.yaml#/definitions/flag + description: + The Write Protect line polarity is inverted. + + cd-inverted: + $ref: /schemas/types.yaml#/definitions/flag + description: + The CD line polarity is inverted. + + # Other properties + + bus-width: + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - enum: [1, 4, 8] + default: 1 + description: + Number of data lines. + + max-frequency: + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - minimum: 400000 + - maximum: 200000000 + description: + Maximum operating frequency of the bus. + + disable-wp: + $ref: /schemas/types.yaml#/definitions/flag + description: + When set, no physical write-protect line is present. This + property should only be specified when the controller has a + dedicated write-protect detection logic. If a GPIO is always + used for the write-protect detection. If a GPIO is always used + for the write-protect detection logic, it is sufficient to not + specify the wp-gpios property in the absence of a write-protect + line. + + wp-gpios: + description: + GPIO to use for the write-protect detection. + + cd-debounce-delay-ms: + description: + Set delay time before detecting card after card insert + interrupt. + + no-1-8-v: + $ref: /schemas/types.yaml#/definitions/flag + description: + When specified, denotes that 1.8V card voltage is not supported + on this system, even if the controller claims it. + + cap-sd-highspeed: + $ref: /schemas/types.yaml#/definitions/flag + description: + SD high-speed timing is supported. + + cap-mmc-highspeed: + $ref: /schemas/types.yaml#/definitions/flag + description: + MMC high-speed timing is supported. + + sd-uhs-sdr12: + $ref: /schemas/types.yaml#/definitions/flag + description: + SD UHS SDR12 speed is supported. + + sd-uhs-sdr25: + $ref: /schemas/types.yaml#/definitions/flag + description: + SD UHS SDR25 speed is supported. + + sd-uhs-sdr50: + $ref: /schemas/types.yaml#/definitions/flag + description: + SD UHS SDR50 speed is supported. + + sd-uhs-sdr104: + $ref: /schemas/types.yaml#/definitions/flag + description: + SD UHS SDR104 speed is supported. + + sd-uhs-ddr50: + $ref: /schemas/types.yaml#/definitions/flag + description: + SD UHS DDR50 speed is supported. + + cap-power-off-card: + $ref: /schemas/types.yaml#/definitions/flag + description: + Powering off the card is safe. + + cap-mmc-hw-reset: + $ref: /schemas/types.yaml#/definitions/flag + description: + eMMC hardware reset is supported + + cap-sdio-irq: + $ref: /schemas/types.yaml#/definitions/flag + description: + enable SDIO IRQ signalling on this interface + + full-pwr-cycle: + $ref: /schemas/types.yaml#/definitions/flag + description: + Full power cycle of the card is supported. + + mmc-ddr-1_2v: + $ref: /schemas/types.yaml#/definitions/flag + description: + eMMC high-speed DDR mode (1.2V I/O) is supported. + + mmc-ddr-1_8v: + $ref: /schemas/types.yaml#/definitions/flag + description: + eMMC high-speed DDR mode (1.8V I/O) is supported. + + mmc-ddr-3_3v: + $ref: /schemas/types.yaml#/definitions/flag + description: + eMMC high-speed DDR mode (3.3V I/O) is supported. + + mmc-hs200-1_2v: + $ref: /schemas/types.yaml#/definitions/flag + description: + eMMC HS200 mode (1.2V I/O) is supported. + + mmc-hs200-1_8v: + $ref: /schemas/types.yaml#/definitions/flag + description: + eMMC HS200 mode (1.8V I/O) is supported. + + mmc-hs400-1_2v: + $ref: /schemas/types.yaml#/definitions/flag + description: + eMMC HS400 mode (1.2V I/O) is supported. + + mmc-hs400-1_8v: + $ref: /schemas/types.yaml#/definitions/flag + description: + eMMC HS400 mode (1.8V I/O) is supported. + + mmc-hs400-enhanced-strobe: + $ref: /schemas/types.yaml#/definitions/flag + description: + eMMC HS400 enhanced strobe mode is supported + + dsr: + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - minimum: 0 + - maximum: 0xffff + description: + Value the card Driver Stage Register (DSR) should be programmed + with. + + no-sdio: + $ref: /schemas/types.yaml#/definitions/flag + description: + Controller is limited to send SDIO commands during + initialization. + + no-sd: + $ref: /schemas/types.yaml#/definitions/flag + description: + Controller is limited to send SD commands during initialization. + + no-mmc: + $ref: /schemas/types.yaml#/definitions/flag + description: + Controller is limited to send MMC commands during + initialization. + + fixed-emmc-driver-type: + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - minimum: 0 + - maximum: 4 + description: + For non-removable eMMC, enforce this driver type. The value is + the driver type as specified in the eMMC specification (table + 206 in spec version 5.1) + + post-power-on-delay-ms: + allOf: + - $ref: /schemas/types.yaml#/definitions/uint32 + - default: 10 + description: + It was invented for MMC pwrseq-simple which could be referred to + mmc-pwrseq-simple.txt. But now it\'s reused as a tunable delay + waiting for I/O signalling and card power supply to be stable, + regardless of whether pwrseq-simple is used. Default to 10ms if + no available. + + supports-cqe: + $ref: /schemas/types.yaml#/definitions/flag + description: + The presence of this property indicates that the corresponding + MMC host controller supports HW command queue feature. + + disable-cqe-dcmd: + $ref: /schemas/types.yaml#/definitions/flag + description: + The presence of this property indicates that the MMC + controller\'s command queue engine (CQE) does not support direct + commands (DCMDs). + + keep-power-in-suspend: + $ref: /schemas/types.yaml#/definitions/flag + description: + SDIO only. Preserves card power during a suspend/resume cycle. + + # Deprecated: enable-sdio-wakeup + wakeup-source: + $ref: /schemas/types.yaml#/definitions/flag + description: + SDIO only. Enables wake up of host system on SDIO IRQ assertion. + + vmmc-supply: + description: + Supply for the card power + + vqmmc-supply: + description: + Supply for the bus IO line power + + mmc-pwrseq: + $ref: /schemas/types.yaml#/definitions/phandle + description: + System-on-Chip designs may specify a specific MMC power + sequence. To successfully detect an (e)MMC/SD/SDIO card, that + power sequence must be maintained while initializing the card. + +patternProperties: + "^.*@[0-9]+$": + type: object + description: | + On embedded systems the cards connected to a host may need + additional properties. These can be specified in subnodes to the + host controller node. The subnodes are identified by the + standard \'reg\' property. Which information exactly can be + specified depends on the bindings for the SDIO function driver + for the subnode, as specified by the compatible string. + + properties: + compatible: + description: | + Name of SDIO function following generic names recommended + practice + + reg: + items: + - minimum: 0 + maximum: 7 + description: + Must contain the SDIO function number of the function this + subnode describes. A value of 0 denotes the memory SD + function, values from 1 to 7 denote the SDIO functions. + + broken-hpi: + $ref: /schemas/types.yaml#/definitions/flag + description: + Use this to indicate that the mmc-card has a broken hpi + implementation, and that hpi should not be used. + + required: + - reg + +dependencies: + cd-debounce-delay-ms: [ cd-gpios ] + fixed-emmc-driver-type: [ non-removable ] + +examples: + - | + sdhci@ab000000 { + compatible = "sdhci"; + reg = <0xab000000 0x200>; + interrupts = <23>; + bus-width = <4>; + cd-gpios = <&gpio 69 0>; + cd-inverted; + wp-gpios = <&gpio 70 0>; + max-frequency = <50000000>; + keep-power-in-suspend; + wakeup-source; + mmc-pwrseq = <&sdhci0_pwrseq>; + }; + + - | + mmc3: mmc@1c12000 { + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&mmc3_pins_a>; + vmmc-supply = <®_vmmc3>; + bus-width = <4>; + non-removable; + mmc-pwrseq = <&sdhci0_pwrseq>; + + brcmf: bcrmf@1 { + reg = <1>; + compatible = "brcm,bcm43xx-fmac"; + interrupt-parent = <&pio>; + interrupts = <10 8>; + interrupt-names = "host-wake"; + }; + }; diff --git a/Documentation/devicetree/bindings/mmc/mmc.txt b/Documentation/devicetree/bindings/mmc/mmc.txt index c269dbe384fe..bf9d7d3febf1 100644 --- a/Documentation/devicetree/bindings/mmc/mmc.txt +++ b/Documentation/devicetree/bindings/mmc/mmc.txt @@ -1,177 +1 @@ -These properties are common to multiple MMC host controllers. Any host -that requires the respective functionality should implement them using -these definitions. - -Interpreted by the OF core: -- reg: Registers location and length. -- interrupts: Interrupts used by the MMC controller. - -Card detection: -If no property below is supplied, host native card detect is used. -Only one of the properties in this section should be supplied: - - broken-cd: There is no card detection available; polling must be used. - - cd-gpios: Specify GPIOs for card detection, see gpio binding - - non-removable: non-removable slot (like eMMC); assume always present. - -Optional properties: -- bus-width: Number of data lines, can be <1>, <4>, or <8>. The default - will be <1> if the property is absent. -- wp-gpios: Specify GPIOs for write protection, see gpio binding -- cd-inverted: when present, polarity on the CD line is inverted. See the note - below for the case, when a GPIO is used for the CD line -- cd-debounce-delay-ms: Set delay time before detecting card after card insert interrupt. - It's only valid when cd-gpios is present. -- wp-inverted: when present, polarity on the WP line is inverted. See the note - below for the case, when a GPIO is used for the WP line -- disable-wp: When set no physical WP line is present. This property should - only be specified when the controller has a dedicated write-protect - detection logic. If a GPIO is always used for the write-protect detection - logic it is sufficient to not specify wp-gpios property in the absence of a WP - line. -- max-frequency: maximum operating clock frequency -- no-1-8-v: when present, denotes that 1.8v card voltage is not supported on - this system, even if the controller claims it is. -- cap-sd-highspeed: SD high-speed timing is supported -- cap-mmc-highspeed: MMC high-speed timing is supported -- sd-uhs-sdr12: SD UHS SDR12 speed is supported -- sd-uhs-sdr25: SD UHS SDR25 speed is supported -- sd-uhs-sdr50: SD UHS SDR50 speed is supported -- sd-uhs-sdr104: SD UHS SDR104 speed is supported -- sd-uhs-ddr50: SD UHS DDR50 speed is supported -- cap-power-off-card: powering off the card is safe -- cap-mmc-hw-reset: eMMC hardware reset is supported -- cap-sdio-irq: enable SDIO IRQ signalling on this interface -- full-pwr-cycle: full power cycle of the card is supported -- mmc-ddr-3_3v: eMMC high-speed DDR mode(3.3V I/O) is supported -- mmc-ddr-1_8v: eMMC high-speed DDR mode(1.8V I/O) is supported -- mmc-ddr-1_2v: eMMC high-speed DDR mode(1.2V I/O) is supported -- mmc-hs200-1_8v: eMMC HS200 mode(1.8V I/O) is supported -- mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported -- mmc-hs400-1_8v: eMMC HS400 mode(1.8V I/O) is supported -- mmc-hs400-1_2v: eMMC HS400 mode(1.2V I/O) is supported -- mmc-hs400-enhanced-strobe: eMMC HS400 enhanced strobe mode is supported -- dsr: Value the card's (optional) Driver Stage Register (DSR) should be - programmed with. Valid range: [0 .. 0xffff]. -- no-sdio: controller is limited to send sdio cmd during initialization -- no-sd: controller is limited to send sd cmd during initialization -- no-mmc: controller is limited to send mmc cmd during initialization -- fixed-emmc-driver-type: for non-removable eMMC, enforce this driver type. - The value is the driver type as specified in the eMMC specification - (table 206 in spec version 5.1). -- post-power-on-delay-ms : It was invented for MMC pwrseq-simple which could - be referred to mmc-pwrseq-simple.txt. But now it's reused as a tunable delay - waiting for I/O signalling and card power supply to be stable, regardless of - whether pwrseq-simple is used. Default to 10ms if no available. -- supports-cqe : The presence of this property indicates that the corresponding - MMC host controller supports HW command queue feature. -- disable-cqe-dcmd: This property indicates that the MMC controller's command - queue engine (CQE) does not support direct commands (DCMDs). - -*NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line -polarity properties, we have to fix the meaning of the "normal" and "inverted" -line levels. We choose to follow the SDHCI standard, which specifies both those -lines as "active low." Therefore, using the "cd-inverted" property means, that -the CD line is active high, i.e. it is high, when a card is inserted. Similar -logic applies to the "wp-inverted" property. - -CD and WP lines can be implemented on the hardware in one of two ways: as GPIOs, -specified in cd-gpios and wp-gpios properties, or as dedicated pins. Polarity of -dedicated pins can be specified, using *-inverted properties. GPIO polarity can -also be specified using the GPIO_ACTIVE_LOW flag. This creates an ambiguity -in the latter case. We choose to use the XOR logic for GPIO CD and WP lines. -This means, the two properties are "superimposed," for example leaving the -GPIO_ACTIVE_LOW flag clear and specifying the respective *-inverted property -property results in a double-inversion and actually means the "normal" line -polarity is in effect. - -Optional SDIO properties: -- keep-power-in-suspend: Preserves card power during a suspend/resume cycle -- wakeup-source: Enables wake up of host system on SDIO IRQ assertion - (Legacy property supported: "enable-sdio-wakeup") - -MMC power ---------- - -Controllers may implement power control from both the connected cards and -the IO signaling (for example to change to high-speed 1.8V signalling). If -the system supports this, then the following two properties should point -to valid regulator nodes: - -- vqmmc-supply: supply node for IO line power -- vmmc-supply: supply node for card's power - - -MMC power sequences: --------------------- - -System on chip designs may specify a specific MMC power sequence. To -successfully detect an (e)MMC/SD/SDIO card, that power sequence must be -maintained while initializing the card. - -Optional property: -- mmc-pwrseq: phandle to the MMC power sequence node. See "mmc-pwrseq-*" - for documentation of MMC power sequence bindings. - - -Use of Function subnodes ------------------------- - -On embedded systems the cards connected to a host may need additional -properties. These can be specified in subnodes to the host controller node. -The subnodes are identified by the standard 'reg' property. -Which information exactly can be specified depends on the bindings for the -SDIO function driver for the subnode, as specified by the compatible string. - -Required host node properties when using function subnodes: -- #address-cells: should be one. The cell is the slot id. -- #size-cells: should be zero. - -Required function subnode properties: -- reg: Must contain the SDIO function number of the function this subnode - describes. A value of 0 denotes the memory SD function, values from - 1 to 7 denote the SDIO functions. - -Optional function subnode properties: -- compatible: name of SDIO function following generic names recommended practice - - -Examples --------- - -Basic example: - -sdhci@ab000000 { - compatible = "sdhci"; - reg = <0xab000000 0x200>; - interrupts = <23>; - bus-width = <4>; - cd-gpios = <&gpio 69 0>; - cd-inverted; - wp-gpios = <&gpio 70 0>; - max-frequency = <50000000>; - keep-power-in-suspend; - wakeup-source; - mmc-pwrseq = <&sdhci0_pwrseq> -} - -Example with sdio function subnode: - -mmc3: mmc@1c12000 { - #address-cells = <1>; - #size-cells = <0>; - - pinctrl-names = "default"; - pinctrl-0 = <&mmc3_pins_a>; - vmmc-supply = <®_vmmc3>; - bus-width = <4>; - non-removable; - mmc-pwrseq = <&sdhci0_pwrseq> - - brcmf: bcrmf@1 { - reg = <1>; - compatible = "brcm,bcm43xx-fmac"; - interrupt-parent = <&pio>; - interrupts = <10 8>; /* PH10 / EINT10 */ - interrupt-names = "host-wake"; - }; -}; +This file has moved to mmc-controller.yaml. -- cgit v1.2.3-59-g8ed1b From ca4570a4c2d3be309ff4b8976efa7c8291ca6b6d Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 29 May 2019 09:23:44 +0200 Subject: dt-bindings: mmc: sun4i: Add YAML schemas Switch the DT binding to a YAML schema to enable the DT validation. Reviewed-by: Rob Herring Signed-off-by: Maxime Ripard Signed-off-by: Ulf Hansson --- .../bindings/mmc/allwinner,sun4i-a10-mmc.yaml | 98 ++++++++++++++++++++++ .../devicetree/bindings/mmc/sunxi-mmc.txt | 52 ------------ 2 files changed, 98 insertions(+), 52 deletions(-) create mode 100644 Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml delete mode 100644 Documentation/devicetree/bindings/mmc/sunxi-mmc.txt diff --git a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml new file mode 100644 index 000000000000..df0280edef97 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml @@ -0,0 +1,98 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/allwinner,sun4i-a10-mmc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner A10 MMC Controller Device Tree Bindings + +allOf: + - $ref: "mmc-controller.yaml" + +maintainers: + - Chen-Yu Tsai + - Maxime Ripard + +properties: + "#address-cells": true + "#size-cells": true + + compatible: + oneOf: + - const: allwinner,sun4i-a10-mmc + - const: allwinner,sun5i-a13-mmc + - const: allwinner,sun7i-a20-mmc + - const: allwinner,sun8i-a83t-emmc + - const: allwinner,sun9i-a80-mmc + - const: allwinner,sun50i-a64-emmc + - const: allwinner,sun50i-a64-mmc + - items: + - const: allwinner,sun8i-a83t-mmc + - const: allwinner,sun7i-a20-mmc + - items: + - const: allwinner,sun50i-h6-emmc + - const: allwinner,sun50i-a64-emmc + - items: + - const: allwinner,sun50i-h6-mmc + - const: allwinner,sun50i-a64-mmc + - items: + - const: allwinner,sun8i-r40-emmc + - const: allwinner,sun50i-a64-emmc + - items: + - const: allwinner,sun8i-r40-mmc + - const: allwinner,sun50i-a64-mmc + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + minItems: 2 + maxItems: 4 + items: + - description: Bus Clock + - description: Module Clock + - description: Output Clock + - description: Sample Clock + + clock-names: + minItems: 2 + maxItems: 4 + items: + - const: ahb + - const: mmc + - const: output + - const: sample + + resets: + maxItems: 1 + + reset-names: + const: ahb + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + +examples: + - | + mmc0: mmc@1c0f000 { + compatible = "allwinner,sun5i-a13-mmc"; + reg = <0x01c0f000 0x1000>; + clocks = <&ahb_gates 8>, <&mmc0_clk>; + clock-names = "ahb", "mmc"; + interrupts = <32>; + bus-width = <4>; + cd-gpios = <&pio 7 1 0>; + }; + +# FIXME: We should set it, but it would report all the generic +# properties as additional properties. +# additionalProperties: false + +... diff --git a/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt b/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt deleted file mode 100644 index e9cb3ec5e502..000000000000 --- a/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt +++ /dev/null @@ -1,52 +0,0 @@ -* Allwinner sunxi MMC controller - -The highspeed MMC host controller on Allwinner SoCs provides an interface -for MMC, SD and SDIO types of memory cards. - -Supported maximum speeds are the ones of the eMMC standard 4.5 as well -as the speed of SD standard 3.0. -Absolute maximum transfer rate is 200MB/s - -Required properties: - - compatible : should be one of: - * "allwinner,sun4i-a10-mmc" - * "allwinner,sun5i-a13-mmc" - * "allwinner,sun7i-a20-mmc" - * "allwinner,sun8i-a83t-emmc" - * "allwinner,sun9i-a80-mmc" - * "allwinner,sun50i-a64-emmc" - * "allwinner,sun50i-a64-mmc" - * "allwinner,sun50i-h6-emmc", "allwinner.sun50i-a64-emmc" - * "allwinner,sun50i-h6-mmc", "allwinner.sun50i-a64-mmc" - - reg : mmc controller base registers - - clocks : a list with 4 phandle + clock specifier pairs - - clock-names : must contain "ahb", "mmc", "output" and "sample" - - interrupts : mmc controller interrupt - -Optional properties: - - resets : phandle + reset specifier pair - - reset-names : must contain "ahb" - - for cd, bus-width and additional generic mmc parameters - please refer to mmc.txt within this directory - -Examples: - - Within .dtsi: - mmc0: mmc@1c0f000 { - compatible = "allwinner,sun5i-a13-mmc"; - reg = <0x01c0f000 0x1000>; - clocks = <&ahb_gates 8>, <&mmc0_clk>, <&mmc0_output_clk>, <&mmc0_sample_clk>; - clock-names = "ahb", "mod", "output", "sample"; - interrupts = <0 32 4>; - status = "disabled"; - }; - - - Within dts: - mmc0: mmc@1c0f000 { - pinctrl-names = "default", "default"; - pinctrl-0 = <&mmc0_pins_a>; - pinctrl-1 = <&mmc0_cd_pin_reference_design>; - bus-width = <4>; - cd-gpios = <&pio 7 1 0>; /* PH1 */ - cd-inverted; - status = "okay"; - }; -- cgit v1.2.3-59-g8ed1b From 90298dc353bc1327d59da30d4b1e4d50d5513033 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 31 May 2019 12:32:23 +0100 Subject: mmc: sdhci-pci: remove redundant check of slots == 0 The calculation of slots results in a value in the range 1..8 and so slots can never be zero. The check for slots == 0 is always going to be false, hence it is redundant and can be removed. Addresses-Coverity: ("Logically dead code") Signed-off-by: Colin Ian King Acked-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pci-core.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 4154ee11b47d..fa6a8fa560c3 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -2040,8 +2040,6 @@ static int sdhci_pci_probe(struct pci_dev *pdev, slots = PCI_SLOT_INFO_SLOTS(slots) + 1; dev_dbg(&pdev->dev, "found %d slot(s)\n", slots); - if (slots == 0) - return -ENODEV; BUG_ON(slots > MAX_SLOTS); -- cgit v1.2.3-59-g8ed1b From 1d94717ddcc7bca9482b8a2f22cd2cac7ce2ca50 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Tue, 4 Jun 2019 16:14:21 +0800 Subject: mmc: sdhci-sprd: Check the enable clock's return value correctly Missed to check the enable clock's return value, fix it. Signed-off-by: Baolin Wang Acked-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-sprd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index 9a822e2e9f0b..e7414918e100 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -368,7 +368,7 @@ static int sdhci_sprd_probe(struct platform_device *pdev) if (ret) goto pltfm_free; - clk_prepare_enable(sprd_host->clk_enable); + ret = clk_prepare_enable(sprd_host->clk_enable); if (ret) goto clk_disable; -- cgit v1.2.3-59-g8ed1b From 334eb9bcb94f6e02d96268b76dd270a399643176 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Tue, 4 Jun 2019 16:14:22 +0800 Subject: dt-bindings: mmc: sprd: Add another optional clock documentation For some Spreadtrum platforms like SC9860 platform, we should enable another gate clock '2x_enable' to make the SD host controller work well. Thus add documentation for this optional clock. Signed-off-by: Baolin Wang Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/sdhci-sprd.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mmc/sdhci-sprd.txt b/Documentation/devicetree/bindings/mmc/sdhci-sprd.txt index 45c9978aad7b..a285c773acd0 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-sprd.txt +++ b/Documentation/devicetree/bindings/mmc/sdhci-sprd.txt @@ -14,6 +14,7 @@ Required properties: - clock-names: Should contain the following: "sdio" - SDIO source clock (required) "enable" - gate clock which used for enabling/disabling the device (required) + "2x_enable" - gate clock controlling the device for some special platforms (optional) Optional properties: - assigned-clocks: the same with "sdio" clock -- cgit v1.2.3-59-g8ed1b From ebd88a38dbf91c496ec1167c1d9a4eaf095dd704 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Tue, 4 Jun 2019 16:14:23 +0800 Subject: mmc: sdhci-sprd: Add optional gate clock support For the Spreadtrum SC9860 platform, we should enable another gate clock '2x_enable' to make the SD host controller work well. Signed-off-by: Baolin Wang Acked-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-sprd.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index e7414918e100..31ba7d65369f 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -60,6 +60,7 @@ struct sdhci_sprd_host { u32 version; struct clk *clk_sdio; struct clk *clk_enable; + struct clk *clk_2x_enable; u32 base_rate; int flags; /* backup of host attribute */ }; @@ -364,6 +365,10 @@ static int sdhci_sprd_probe(struct platform_device *pdev) } sprd_host->clk_enable = clk; + clk = devm_clk_get(&pdev->dev, "2x_enable"); + if (!IS_ERR(clk)) + sprd_host->clk_2x_enable = clk; + ret = clk_prepare_enable(sprd_host->clk_sdio); if (ret) goto pltfm_free; @@ -372,6 +377,10 @@ static int sdhci_sprd_probe(struct platform_device *pdev) if (ret) goto clk_disable; + ret = clk_prepare_enable(sprd_host->clk_2x_enable); + if (ret) + goto clk_disable2; + sdhci_sprd_init_config(host); host->version = sdhci_readw(host, SDHCI_HOST_VERSION); sprd_host->version = ((host->version & SDHCI_VENDOR_VER_MASK) >> @@ -408,6 +417,9 @@ pm_runtime_disable: pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); + clk_disable_unprepare(sprd_host->clk_2x_enable); + +clk_disable2: clk_disable_unprepare(sprd_host->clk_enable); clk_disable: @@ -427,6 +439,7 @@ static int sdhci_sprd_remove(struct platform_device *pdev) mmc_remove_host(mmc); clk_disable_unprepare(sprd_host->clk_sdio); clk_disable_unprepare(sprd_host->clk_enable); + clk_disable_unprepare(sprd_host->clk_2x_enable); mmc_free_host(mmc); @@ -449,6 +462,7 @@ static int sdhci_sprd_runtime_suspend(struct device *dev) clk_disable_unprepare(sprd_host->clk_sdio); clk_disable_unprepare(sprd_host->clk_enable); + clk_disable_unprepare(sprd_host->clk_2x_enable); return 0; } @@ -459,19 +473,28 @@ static int sdhci_sprd_runtime_resume(struct device *dev) struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host); int ret; - ret = clk_prepare_enable(sprd_host->clk_enable); + ret = clk_prepare_enable(sprd_host->clk_2x_enable); if (ret) return ret; + ret = clk_prepare_enable(sprd_host->clk_enable); + if (ret) + goto clk_2x_disable; + ret = clk_prepare_enable(sprd_host->clk_sdio); - if (ret) { - clk_disable_unprepare(sprd_host->clk_enable); - return ret; - } + if (ret) + goto clk_disable; sdhci_runtime_resume_host(host); - return 0; + +clk_disable: + clk_disable_unprepare(sprd_host->clk_enable); + +clk_2x_disable: + clk_disable_unprepare(sprd_host->clk_2x_enable); + + return ret; } #endif -- cgit v1.2.3-59-g8ed1b From 7486831d7d6aebcf851f9a4bbe65080351d5c9fb Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Tue, 4 Jun 2019 16:14:24 +0800 Subject: mmc: sdhci-sprd: Implement the get_max_timeout_count() interface Implement the get_max_timeout_count() interface to set the Spredtrum SD host controller actual maximum timeout count. Signed-off-by: Baolin Wang Acked-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-sprd.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index 31ba7d65369f..d91281d02cdb 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -285,6 +285,12 @@ static void sdhci_sprd_hw_reset(struct sdhci_host *host) usleep_range(300, 500); } +static unsigned int sdhci_sprd_get_max_timeout_count(struct sdhci_host *host) +{ + /* The Spredtrum controller actual maximum timeout count is 1 << 31 */ + return 1 << 31; +} + static struct sdhci_ops sdhci_sprd_ops = { .read_l = sdhci_sprd_readl, .write_l = sdhci_sprd_writel, @@ -296,6 +302,7 @@ static struct sdhci_ops sdhci_sprd_ops = { .reset = sdhci_reset, .set_uhs_signaling = sdhci_sprd_set_uhs_signaling, .hw_reset = sdhci_sprd_hw_reset, + .get_max_timeout_count = sdhci_sprd_get_max_timeout_count, }; static void sdhci_sprd_request(struct mmc_host *mmc, struct mmc_request *mrq) -- cgit v1.2.3-59-g8ed1b From 494c11e1a5366d3f5adb2cb2b677b5b0bcf08e3b Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Tue, 4 Jun 2019 16:14:25 +0800 Subject: mmc: sdhci-sprd: Add HS400 enhanced strobe mode Add HS400 enhanced strobe mode support for Spreadtrum SD host controller. Signed-off-by: Baolin Wang Acked-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-sprd.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index d91281d02cdb..edec19755ecd 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -41,6 +41,7 @@ /* SDHCI_HOST_CONTROL2 */ #define SDHCI_SPRD_CTRL_HS200 0x0005 #define SDHCI_SPRD_CTRL_HS400 0x0006 +#define SDHCI_SPRD_CTRL_HS400ES 0x0007 /* * According to the standard specification, BIT(3) of SDHCI_SOFTWARE_RESET is @@ -132,6 +133,15 @@ static inline void sdhci_sprd_sd_clk_off(struct sdhci_host *host) sdhci_writew(host, ctrl, SDHCI_CLOCK_CONTROL); } +static inline void sdhci_sprd_sd_clk_on(struct sdhci_host *host) +{ + u16 ctrl; + + ctrl = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + ctrl |= SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, ctrl, SDHCI_CLOCK_CONTROL); +} + static inline void sdhci_sprd_set_dll_invert(struct sdhci_host *host, u32 mask, bool en) { @@ -325,6 +335,26 @@ static void sdhci_sprd_request(struct mmc_host *mmc, struct mmc_request *mrq) sdhci_request(mmc, mrq); } +static void sdhci_sprd_hs400_enhanced_strobe(struct mmc_host *mmc, + struct mmc_ios *ios) +{ + struct sdhci_host *host = mmc_priv(mmc); + u16 ctrl_2; + + if (!ios->enhanced_strobe) + return; + + sdhci_sprd_sd_clk_off(host); + + /* Set HS400 enhanced strobe mode */ + ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); + ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; + ctrl_2 |= SDHCI_SPRD_CTRL_HS400ES; + sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); + + sdhci_sprd_sd_clk_on(host); +} + static const struct sdhci_pltfm_data sdhci_sprd_pdata = { .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK, .quirks2 = SDHCI_QUIRK2_BROKEN_HS200 | @@ -346,6 +376,8 @@ static int sdhci_sprd_probe(struct platform_device *pdev) host->dma_mask = DMA_BIT_MASK(64); pdev->dev.dma_mask = &host->dma_mask; host->mmc_host_ops.request = sdhci_sprd_request; + host->mmc_host_ops.hs400_enhanced_strobe = + sdhci_sprd_hs400_enhanced_strobe; host->mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_ERASE | MMC_CAP_CMD23; -- cgit v1.2.3-59-g8ed1b From 87a395c27bfab5048413ea18287f0f9453e3e31a Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Tue, 4 Jun 2019 16:14:26 +0800 Subject: mmc: sdhci-sprd: Enable PHY DLL to make clock stable For the Spreadtrum SD host controller, when we changed the clock to be more than 52M, we should enable the PHY DLL which is used to track the clock frequency to make the clock work more stable. Otherwise deviation may occur of the higher clock. Signed-off-by: Baolin Wang Acked-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-sprd.c | 44 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index edec19755ecd..e6eda13e34ea 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -22,6 +22,13 @@ /* SDHCI_ARGUMENT2 register high 16bit */ #define SDHCI_SPRD_ARG2_STUFF GENMASK(31, 16) +#define SDHCI_SPRD_REG_32_DLL_CFG 0x200 +#define SDHCI_SPRD_DLL_ALL_CPST_EN (BIT(18) | BIT(24) | BIT(25) | BIT(26) | BIT(27)) +#define SDHCI_SPRD_DLL_EN BIT(21) +#define SDHCI_SPRD_DLL_SEARCH_MODE BIT(16) +#define SDHCI_SPRD_DLL_INIT_COUNT 0xc00 +#define SDHCI_SPRD_DLL_PHASE_INTERNAL 0x3 + #define SDHCI_SPRD_REG_32_DLL_DLY_OFFSET 0x208 #define SDHCIBSPRD_IT_WR_DLY_INV BIT(5) #define SDHCI_SPRD_BIT_CMD_DLY_INV BIT(13) @@ -56,6 +63,7 @@ #define SDHCI_SPRD_CLK_MAX_DIV 1023 #define SDHCI_SPRD_CLK_DEF_RATE 26000000 +#define SDHCI_SPRD_PHY_DLL_CLK 52000000 struct sdhci_sprd_host { u32 version; @@ -200,9 +208,33 @@ static inline void _sdhci_sprd_set_clock(struct sdhci_host *host, } } +static void sdhci_sprd_enable_phy_dll(struct sdhci_host *host) +{ + u32 tmp; + + tmp = sdhci_readl(host, SDHCI_SPRD_REG_32_DLL_CFG); + tmp &= ~(SDHCI_SPRD_DLL_EN | SDHCI_SPRD_DLL_ALL_CPST_EN); + sdhci_writel(host, tmp, SDHCI_SPRD_REG_32_DLL_CFG); + /* wait 1ms */ + usleep_range(1000, 1250); + + tmp = sdhci_readl(host, SDHCI_SPRD_REG_32_DLL_CFG); + tmp |= SDHCI_SPRD_DLL_ALL_CPST_EN | SDHCI_SPRD_DLL_SEARCH_MODE | + SDHCI_SPRD_DLL_INIT_COUNT | SDHCI_SPRD_DLL_PHASE_INTERNAL; + sdhci_writel(host, tmp, SDHCI_SPRD_REG_32_DLL_CFG); + /* wait 1ms */ + usleep_range(1000, 1250); + + tmp = sdhci_readl(host, SDHCI_SPRD_REG_32_DLL_CFG); + tmp |= SDHCI_SPRD_DLL_EN; + sdhci_writel(host, tmp, SDHCI_SPRD_REG_32_DLL_CFG); + /* wait 1ms */ + usleep_range(1000, 1250); +} + static void sdhci_sprd_set_clock(struct sdhci_host *host, unsigned int clock) { - bool en = false; + bool en = false, clk_changed = false; if (clock == 0) { sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); @@ -214,9 +246,19 @@ static void sdhci_sprd_set_clock(struct sdhci_host *host, unsigned int clock) en = true; sdhci_sprd_set_dll_invert(host, SDHCI_SPRD_BIT_CMD_DLY_INV | SDHCI_SPRD_BIT_POSRD_DLY_INV, en); + clk_changed = true; } else { _sdhci_sprd_set_clock(host, clock); } + + /* + * According to the Spreadtrum SD host specification, when we changed + * the clock to be more than 52M, we should enable the PHY DLL which + * is used to track the clock frequency to make the clock work more + * stable. Otherwise deviation may occur of the higher clock. + */ + if (clk_changed && clock > SDHCI_SPRD_PHY_DLL_CLK) + sdhci_sprd_enable_phy_dll(host); } static unsigned int sdhci_sprd_get_max_clock(struct sdhci_host *host) -- cgit v1.2.3-59-g8ed1b From c8ff5351b598cd722c9cf8a84259887bd1af2e0e Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Tue, 4 Jun 2019 16:14:27 +0800 Subject: dt-bindings: mmc: sprd: Add PHY DLL delay documentation Introduce some PHY DLL delays properties to help to sample the PHY clock. Signed-off-by: Baolin Wang Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/sdhci-sprd.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/sdhci-sprd.txt b/Documentation/devicetree/bindings/mmc/sdhci-sprd.txt index a285c773acd0..e675397fa428 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-sprd.txt +++ b/Documentation/devicetree/bindings/mmc/sdhci-sprd.txt @@ -20,6 +20,23 @@ Optional properties: - assigned-clocks: the same with "sdio" clock - assigned-clock-parents: the default parent of "sdio" clock +PHY DLL delays are used to delay the data valid window, and align the window +to sampling clock. PHY DLL delays can be configured by following properties, +and each property contains 4 cells which are used to configure the clock data +write line delay value, clock read command line delay value, clock read data +positive edge delay value and clock read data negative edge delay value. +Each cell's delay value unit is cycle of the PHY clock. + +- sprd,phy-delay-legacy: Delay value for legacy timing. +- sprd,phy-delay-sd-highspeed: Delay value for SD high-speed timing. +- sprd,phy-delay-sd-uhs-sdr50: Delay value for SD UHS SDR50 timing. +- sprd,phy-delay-sd-uhs-sdr104: Delay value for SD UHS SDR50 timing. +- sprd,phy-delay-mmc-highspeed: Delay value for MMC high-speed timing. +- sprd,phy-delay-mmc-ddr52: Delay value for MMC DDR52 timing. +- sprd,phy-delay-mmc-hs200: Delay value for MMC HS200 timing. +- sprd,phy-delay-mmc-hs400: Delay value for MMC HS400 timing. +- sprd,phy-delay-mmc-hs400es: Delay value for MMC HS400 enhanced strobe timing. + Examples: sdio0: sdio@20600000 { @@ -33,6 +50,7 @@ sdio0: sdio@20600000 { assigned-clocks = <&ap_clk CLK_EMMC_2X>; assigned-clock-parents = <&rpll CLK_RPLL_390M>; + sprd,phy-delay-sd-uhs-sdr104 = <0x3f 0x7f 0x2e 0x2e>; bus-width = <8>; non-removable; no-sdio; -- cgit v1.2.3-59-g8ed1b From 5f2f4e0da2b5d4f4a188480c13f40c848a5f7d15 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Tue, 4 Jun 2019 16:14:28 +0800 Subject: mmc: sdhci-sprd: Add PHY DLL delay configuration Set the PHY DLL delay for each timing mode, which is used to sample the clock accurately and make the clock more stable. Signed-off-by: Baolin Wang Acked-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-sprd.c | 51 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index e6eda13e34ea..024c3c5fa979 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -29,6 +29,8 @@ #define SDHCI_SPRD_DLL_INIT_COUNT 0xc00 #define SDHCI_SPRD_DLL_PHASE_INTERNAL 0x3 +#define SDHCI_SPRD_REG_32_DLL_DLY 0x204 + #define SDHCI_SPRD_REG_32_DLL_DLY_OFFSET 0x208 #define SDHCIBSPRD_IT_WR_DLY_INV BIT(5) #define SDHCI_SPRD_BIT_CMD_DLY_INV BIT(13) @@ -72,6 +74,24 @@ struct sdhci_sprd_host { struct clk *clk_2x_enable; u32 base_rate; int flags; /* backup of host attribute */ + u32 phy_delay[MMC_TIMING_MMC_HS400 + 2]; +}; + +struct sdhci_sprd_phy_cfg { + const char *property; + u8 timing; +}; + +static const struct sdhci_sprd_phy_cfg sdhci_sprd_phy_cfgs[] = { + { "sprd,phy-delay-legacy", MMC_TIMING_LEGACY, }, + { "sprd,phy-delay-sd-highspeed", MMC_TIMING_SD_HS, }, + { "sprd,phy-delay-sd-uhs-sdr50", MMC_TIMING_UHS_SDR50, }, + { "sprd,phy-delay-sd-uhs-sdr104", MMC_TIMING_UHS_SDR104, }, + { "sprd,phy-delay-mmc-highspeed", MMC_TIMING_MMC_HS, }, + { "sprd,phy-delay-mmc-ddr52", MMC_TIMING_MMC_DDR52, }, + { "sprd,phy-delay-mmc-hs200", MMC_TIMING_MMC_HS200, }, + { "sprd,phy-delay-mmc-hs400", MMC_TIMING_MMC_HS400, }, + { "sprd,phy-delay-mmc-hs400es", MMC_TIMING_MMC_HS400 + 1, }, }; #define TO_SPRD_HOST(host) sdhci_pltfm_priv(sdhci_priv(host)) @@ -276,6 +296,9 @@ static unsigned int sdhci_sprd_get_min_clock(struct sdhci_host *host) static void sdhci_sprd_set_uhs_signaling(struct sdhci_host *host, unsigned int timing) { + struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host); + struct mmc_host *mmc = host->mmc; + u32 *p = sprd_host->phy_delay; u16 ctrl_2; if (timing == host->timing) @@ -314,6 +337,9 @@ static void sdhci_sprd_set_uhs_signaling(struct sdhci_host *host, } sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); + + if (!mmc->ios.enhanced_strobe) + sdhci_writel(host, p[timing], SDHCI_SPRD_REG_32_DLL_DLY); } static void sdhci_sprd_hw_reset(struct sdhci_host *host) @@ -381,6 +407,8 @@ static void sdhci_sprd_hs400_enhanced_strobe(struct mmc_host *mmc, struct mmc_ios *ios) { struct sdhci_host *host = mmc_priv(mmc); + struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host); + u32 *p = sprd_host->phy_delay; u16 ctrl_2; if (!ios->enhanced_strobe) @@ -395,6 +423,28 @@ static void sdhci_sprd_hs400_enhanced_strobe(struct mmc_host *mmc, sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); sdhci_sprd_sd_clk_on(host); + + /* Set the PHY DLL delay value for HS400 enhanced strobe mode */ + sdhci_writel(host, p[MMC_TIMING_MMC_HS400 + 1], + SDHCI_SPRD_REG_32_DLL_DLY); +} + +static void sdhci_sprd_phy_param_parse(struct sdhci_sprd_host *sprd_host, + struct device_node *np) +{ + u32 *p = sprd_host->phy_delay; + int ret, i, index; + u32 val[4]; + + for (i = 0; i < ARRAY_SIZE(sdhci_sprd_phy_cfgs); i++) { + ret = of_property_read_u32_array(np, + sdhci_sprd_phy_cfgs[i].property, val, 4); + if (ret) + continue; + + index = sdhci_sprd_phy_cfgs[i].timing; + p[index] = val[0] | (val[1] << 8) | (val[2] << 16) | (val[3] << 24); + } } static const struct sdhci_pltfm_data sdhci_sprd_pdata = { @@ -428,6 +478,7 @@ static int sdhci_sprd_probe(struct platform_device *pdev) goto pltfm_free; sprd_host = TO_SPRD_HOST(host); + sdhci_sprd_phy_param_parse(sprd_host, pdev->dev.of_node); clk = devm_clk_get(&pdev->dev, "sdio"); if (IS_ERR(clk)) { -- cgit v1.2.3-59-g8ed1b From 00a9584eadf39b12dac7495250dc508c6b106f81 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 4 Jun 2019 17:34:46 +0200 Subject: sdhci: tegra: Do not log error message on deferred probe Recent changes have made it much more likely that clocks are not available, when the SDHCI driver is first probed. However, that is a situation that the driver can cope with just fine. To avoid confusion, don't output an error when this happens. Signed-off-by: Thierry Reding Acked-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-tegra.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 781a3e106d9a..f4d4761cf20a 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -1541,8 +1541,11 @@ static int sdhci_tegra_probe(struct platform_device *pdev) clk = devm_clk_get(mmc_dev(host->mmc), NULL); if (IS_ERR(clk)) { - dev_err(mmc_dev(host->mmc), "clk err\n"); rc = PTR_ERR(clk); + + if (rc != -EPROBE_DEFER) + dev_err(&pdev->dev, "failed to get clock: %d\n", rc); + goto err_clk_get; } clk_prepare_enable(clk); -- cgit v1.2.3-59-g8ed1b From 6a6869869a37e61ec0521653bacc8f39dfaae0e2 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 6 Jun 2019 13:35:36 +0200 Subject: mmc: sdhi: improve quirk descriptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Quirks show up in new SoCs as well, so the naming should be generic. Describe them by what they do. Signed-off-by: Wolfram Sang Reviewed-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 683c449a2f94..24857ced9f2e 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -610,12 +610,12 @@ static void renesas_sdhi_enable_dma(struct tmio_mmc_host *host, bool enable) renesas_sdhi_sdbuf_width(host, enable ? width : 16); } -static const struct renesas_sdhi_quirks sdhi_quirks_h3_m3w_es1 = { +static const struct renesas_sdhi_quirks sdhi_quirks_4tap_nohs400 = { .hs400_disabled = true, .hs400_4taps = true, }; -static const struct renesas_sdhi_quirks sdhi_quirks_h3_es2 = { +static const struct renesas_sdhi_quirks sdhi_quirks_4tap = { .hs400_disabled = false, .hs400_4taps = true, }; @@ -625,10 +625,10 @@ static const struct renesas_sdhi_quirks sdhi_quirks_nohs400 = { }; static const struct soc_device_attribute sdhi_quirks_match[] = { - { .soc_id = "r8a7795", .revision = "ES1.*", .data = &sdhi_quirks_h3_m3w_es1 }, - { .soc_id = "r8a7795", .revision = "ES2.0", .data = &sdhi_quirks_h3_es2 }, - { .soc_id = "r8a7796", .revision = "ES1.[012]", .data = &sdhi_quirks_h3_m3w_es1 }, - { .soc_id = "r8a774a1", .revision = "ES1.[012]", .data = &sdhi_quirks_h3_m3w_es1 }, + { .soc_id = "r8a7795", .revision = "ES1.*", .data = &sdhi_quirks_4tap_nohs400 }, + { .soc_id = "r8a7795", .revision = "ES2.0", .data = &sdhi_quirks_4tap }, + { .soc_id = "r8a7796", .revision = "ES1.[012]", .data = &sdhi_quirks_4tap_nohs400 }, + { .soc_id = "r8a774a1", .revision = "ES1.[012]", .data = &sdhi_quirks_4tap_nohs400 }, { .soc_id = "r8a77980", .data = &sdhi_quirks_nohs400 }, { /* Sentinel. */ }, }; -- cgit v1.2.3-59-g8ed1b From ef4a8d90b7f495a5b32375e33d5d2fd763a6a18c Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 6 Jun 2019 13:35:37 +0200 Subject: mmc: sdhi: remove unneeded initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bools are initialized to 'false' by default. Signed-off-by: Wolfram Sang Reviewed-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Signed-off-by: Ulf Hansson --- drivers/mmc/host/renesas_sdhi_core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 24857ced9f2e..64d3b5fb7fe5 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -616,7 +616,6 @@ static const struct renesas_sdhi_quirks sdhi_quirks_4tap_nohs400 = { }; static const struct renesas_sdhi_quirks sdhi_quirks_4tap = { - .hs400_disabled = false, .hs400_4taps = true, }; -- cgit v1.2.3-59-g8ed1b From a457b70904bbf9a96d39fa01ce4d04a1d10c5e44 Mon Sep 17 00:00:00 2001 From: Faiz Abbas Date: Tue, 4 Jun 2019 11:39:11 +0530 Subject: dt-bindings: mmc: sdhci-am654: Document bindings for the host controllers on TI's J721E devices. Add binding documentation for mmc host controllers present on TI's J721E SOC. The 4 bit IP on J721E doesn't have a phy DLL so make DLL related properties as optional for that compatible. Also add an optional strobe-sel property used for HS400 speed mode. Signed-off-by: Faiz Abbas Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/sdhci-am654.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mmc/sdhci-am654.txt b/Documentation/devicetree/bindings/mmc/sdhci-am654.txt index 15dbbbace27e..50e87df47971 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-am654.txt +++ b/Documentation/devicetree/bindings/mmc/sdhci-am654.txt @@ -8,7 +8,10 @@ Only deviations are documented here. [3] Documentation/devicetree/bindings/interrupt-controller/interrupts.txt Required Properties: - - compatible: should be "ti,am654-sdhci-5.1" + - 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. - reg: Must be two entries. - The first should be the sdhci register space - The second should the subsystem/phy register space @@ -16,9 +19,13 @@ Required Properties: - clock-names: Tuple including "clk_xin" and "clk_ahb" - interrupts: Interrupt specifiers - ti,otap-del-sel: Output Tap Delay select + +Optional Properties (Required for ti,am654-sdhci-5.1 and ti,j721e-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. Example: -- cgit v1.2.3-59-g8ed1b From 99909b55f2982e548f594e8c8e2310b50d3254ce Mon Sep 17 00:00:00 2001 From: Faiz Abbas Date: Tue, 4 Jun 2019 11:39:12 +0530 Subject: mmc: sdhci_am654: Add Support for 8 bit IP on J721E The 8 bit IP on the TI's J721E device departs from the AM654x IP in some ways which require special handling. Create a driver_data structure which holds the pltfm_data and a flags field which is used to indicate these differences. These are the following: 1. The pins are not muxed with anything else inside the SoC and hence the IOMUX_ENABLE field does not exist. Add a flag which is used to indicate the presence of the field. 2. The register field used to select DLL frequency is 3 bit wide as compared to 2 bits in AM65x. Add another flag which differentiates between 3 bit and 2 bit fields. 3. The strobe select field is 8 bit wide as compared to 4 bits for AM65x. Add yet another flag to indicate this difference. Strobe select is used only for HS400 speed mode, support for which has not yet been added in AM65x. Signed-off-by: Faiz Abbas Acked-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci_am654.c | 135 +++++++++++++++++++++++++++++++++-------- 1 file changed, 110 insertions(+), 25 deletions(-) diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index d0b20780dd0f..4575aeb435ec 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -6,6 +6,7 @@ * */ #include +#include #include #include #include @@ -36,11 +37,14 @@ #define OTAPDLYSEL_SHIFT 12 #define OTAPDLYSEL_MASK GENMASK(15, 12) #define STRBSEL_SHIFT 24 -#define STRBSEL_MASK GENMASK(27, 24) +#define STRBSEL_4BIT_MASK GENMASK(27, 24) +#define STRBSEL_8BIT_MASK GENMASK(31, 24) #define SEL50_SHIFT 8 #define SEL50_MASK BIT(SEL50_SHIFT) #define SEL100_SHIFT 9 #define SEL100_MASK BIT(SEL100_SHIFT) +#define FREQSEL_SHIFT 8 +#define FREQSEL_MASK GENMASK(10, 8) #define DLL_TRIM_ICP_SHIFT 4 #define DLL_TRIM_ICP_MASK GENMASK(7, 4) #define DR_TY_SHIFT 20 @@ -77,13 +81,23 @@ struct sdhci_am654_data { 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) }; static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); - int sel50, sel100; + int sel50, sel100, freqsel; u32 mask, val; int ret; @@ -101,24 +115,52 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) val = (1 << OTAPDLYENA_SHIFT) | (sdhci_am654->otap_del_sel << OTAPDLYSEL_SHIFT); regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val); - switch (clock) { - case 200000000: - sel50 = 0; - sel100 = 0; - break; - case 100000000: - sel50 = 0; - sel100 = 1; - break; - default: - sel50 = 1; - sel100 = 0; + /* Write to STRBSEL for HS400 speed mode */ + if (host->mmc->ios.timing == MMC_TIMING_MMC_HS400) { + if (sdhci_am654->flags & STRBSEL_4_BIT) + mask = STRBSEL_4BIT_MASK; + else + mask = STRBSEL_8BIT_MASK; + + regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, + sdhci_am654->strb_sel << + STRBSEL_SHIFT); + } + + if (sdhci_am654->flags & FREQSEL_2_BIT) { + switch (clock) { + case 200000000: + sel50 = 0; + sel100 = 0; + break; + case 100000000: + sel50 = 0; + sel100 = 1; + break; + default: + sel50 = 1; + sel100 = 0; + } + + /* Configure PHY DLL frequency */ + mask = SEL50_MASK | SEL100_MASK; + val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT); + regmap_update_bits(sdhci_am654->base, PHY_CTRL5, mask, + val); + } else { + switch (clock) { + case 200000000: + freqsel = 0x0; + break; + default: + freqsel = 0x4; + } + + regmap_update_bits(sdhci_am654->base, PHY_CTRL5, + FREQSEL_MASK, + freqsel << FREQSEL_SHIFT); } - /* Configure PHY DLL frequency */ - mask = SEL50_MASK | SEL100_MASK; - val = (sel50 << SEL50_SHIFT) | (sel100 << SEL100_SHIFT); - regmap_update_bits(sdhci_am654->base, PHY_CTRL5, mask, val); /* Configure DLL TRIM */ mask = DLL_TRIM_ICP_MASK; val = sdhci_am654->trm_icp << DLL_TRIM_ICP_SHIFT; @@ -196,6 +238,33 @@ static const struct sdhci_pltfm_data sdhci_am654_pdata = { .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, }; +static const struct sdhci_am654_driver_data sdhci_am654_drvdata = { + .pdata = &sdhci_am654_pdata, + .flags = IOMUX_PRESENT | FREQSEL_2_BIT | STRBSEL_4_BIT, +}; + +struct sdhci_ops sdhci_j721e_8bit_ops = { + .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, + .set_bus_width = sdhci_set_bus_width, + .set_power = sdhci_am654_set_power, + .set_clock = sdhci_am654_set_clock, + .write_b = sdhci_am654_write_b, + .reset = sdhci_reset, +}; + +static const struct sdhci_pltfm_data sdhci_j721e_8bit_pdata = { + .ops = &sdhci_j721e_8bit_ops, + .quirks = SDHCI_QUIRK_INVERTED_WRITE_PROTECT | + SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, +}; + +static const struct sdhci_am654_driver_data sdhci_j721e_8bit_drvdata = { + .pdata = &sdhci_j721e_8bit_pdata, +}; + static int sdhci_am654_init(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -221,7 +290,9 @@ static int sdhci_am654_init(struct sdhci_host *host) } /* Enable pins by setting IO mux to 0 */ - regmap_update_bits(sdhci_am654->base, PHY_CTRL1, IOMUX_ENABLE_MASK, 0); + if (sdhci_am654->flags & IOMUX_PRESENT) + regmap_update_bits(sdhci_am654->base, PHY_CTRL1, + IOMUX_ENABLE_MASK, 0); /* Set slot type based on SD or eMMC */ if (host->mmc->caps & MMC_CAP_NONREMOVABLE) @@ -276,15 +347,31 @@ static int sdhci_am654_get_of_property(struct platform_device *pdev, return -EINVAL; } + device_property_read_u32(dev, "ti,strobe-sel", &sdhci_am654->strb_sel); + sdhci_get_of_property(pdev); return 0; } +static const struct of_device_id sdhci_am654_of_match[] = { + { + .compatible = "ti,am654-sdhci-5.1", + .data = &sdhci_am654_drvdata, + }, + { + .compatible = "ti,j721e-sdhci-8bit", + .data = &sdhci_j721e_8bit_drvdata, + }, + { /* sentinel */ } +}; + static int sdhci_am654_probe(struct platform_device *pdev) { + const struct sdhci_am654_driver_data *drvdata; struct sdhci_pltfm_host *pltfm_host; struct sdhci_am654_data *sdhci_am654; + const struct of_device_id *match; struct sdhci_host *host; struct resource *res; struct clk *clk_xin; @@ -292,12 +379,15 @@ static int sdhci_am654_probe(struct platform_device *pdev) void __iomem *base; int ret; - host = sdhci_pltfm_init(pdev, &sdhci_am654_pdata, sizeof(*sdhci_am654)); + match = of_match_node(sdhci_am654_of_match, pdev->dev.of_node); + drvdata = match->data; + host = sdhci_pltfm_init(pdev, drvdata->pdata, sizeof(*sdhci_am654)); if (IS_ERR(host)) return PTR_ERR(host); pltfm_host = sdhci_priv(host); sdhci_am654 = sdhci_pltfm_priv(pltfm_host); + sdhci_am654->flags = drvdata->flags; clk_xin = devm_clk_get(dev, "clk_xin"); if (IS_ERR(clk_xin)) { @@ -372,11 +462,6 @@ static int sdhci_am654_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id sdhci_am654_of_match[] = { - { .compatible = "ti,am654-sdhci-5.1" }, - { /* sentinel */ } -}; - static struct platform_driver sdhci_am654_driver = { .driver = { .name = "sdhci-am654", -- cgit v1.2.3-59-g8ed1b From 1accbced1c3273ead1d30de14339c4a39062bee0 Mon Sep 17 00:00:00 2001 From: Faiz Abbas Date: Tue, 4 Jun 2019 11:39:13 +0530 Subject: mmc: sdhci_am654: Add Support for 4 bit IP on J721E Add support for 4 bit instances on TI's J721E devices. Because these instances have no DLL, introduce a DLL_PRESENT flag and make sure DLL related registers are only accessed when it is present. Also add a separate set_clock callback for this compatible. Signed-off-by: Faiz Abbas Acked-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci_am654.c | 124 ++++++++++++++++++++++++++++------------- 1 file changed, 86 insertions(+), 38 deletions(-) diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index 4575aeb435ec..3b3948144591 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -91,6 +91,7 @@ struct sdhci_am654_driver_data { #define IOMUX_PRESENT (1 << 0) #define FREQSEL_2_BIT (1 << 1) #define STRBSEL_4_BIT (1 << 2) +#define DLL_PRESENT (1 << 3) }; static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) @@ -188,6 +189,20 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) } } +void sdhci_j721e_4bit_set_clock(struct sdhci_host *host, unsigned int clock) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); + int val, mask; + + mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; + val = (1 << OTAPDLYENA_SHIFT) | + (sdhci_am654->otap_del_sel << OTAPDLYSEL_SHIFT); + regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val); + + sdhci_set_clock(host, clock); +} + static void sdhci_am654_set_power(struct sdhci_host *host, unsigned char mode, unsigned short vdd) { @@ -240,7 +255,7 @@ static const struct sdhci_pltfm_data sdhci_am654_pdata = { static const struct sdhci_am654_driver_data sdhci_am654_drvdata = { .pdata = &sdhci_am654_pdata, - .flags = IOMUX_PRESENT | FREQSEL_2_BIT | STRBSEL_4_BIT, + .flags = IOMUX_PRESENT | FREQSEL_2_BIT | STRBSEL_4_BIT | DLL_PRESENT, }; struct sdhci_ops sdhci_j721e_8bit_ops = { @@ -263,8 +278,31 @@ static const struct sdhci_pltfm_data sdhci_j721e_8bit_pdata = { static const struct sdhci_am654_driver_data sdhci_j721e_8bit_drvdata = { .pdata = &sdhci_j721e_8bit_pdata, + .flags = DLL_PRESENT, +}; + +struct sdhci_ops sdhci_j721e_4bit_ops = { + .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, + .set_bus_width = sdhci_set_bus_width, + .set_power = sdhci_am654_set_power, + .set_clock = sdhci_j721e_4bit_set_clock, + .write_b = sdhci_am654_write_b, + .reset = sdhci_reset, +}; + +static const struct sdhci_pltfm_data sdhci_j721e_4bit_pdata = { + .ops = &sdhci_j721e_4bit_ops, + .quirks = SDHCI_QUIRK_INVERTED_WRITE_PROTECT | + SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, }; +static const struct sdhci_am654_driver_data sdhci_j721e_4bit_drvdata = { + .pdata = &sdhci_j721e_4bit_pdata, + .flags = IOMUX_PRESENT, +}; static int sdhci_am654_init(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -278,15 +316,19 @@ static int sdhci_am654_init(struct sdhci_host *host) mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, 0x0); - regmap_read(sdhci_am654->base, PHY_STAT1, &val); - if (~val & CALDONE_MASK) { - /* Calibrate IO lines */ - regmap_update_bits(sdhci_am654->base, PHY_CTRL1, - PDB_MASK, PDB_MASK); - ret = regmap_read_poll_timeout(sdhci_am654->base, PHY_STAT1, - val, val & CALDONE_MASK, 1, 20); - if (ret) - return ret; + if (sdhci_am654->flags & DLL_PRESENT) { + regmap_read(sdhci_am654->base, PHY_STAT1, &val); + if (~val & CALDONE_MASK) { + /* Calibrate IO lines */ + regmap_update_bits(sdhci_am654->base, PHY_CTRL1, + PDB_MASK, PDB_MASK); + ret = regmap_read_poll_timeout(sdhci_am654->base, + PHY_STAT1, val, + val & CALDONE_MASK, + 1, 20); + if (ret) + return ret; + } } /* Enable pins by setting IO mux to 0 */ @@ -311,40 +353,42 @@ static int sdhci_am654_get_of_property(struct platform_device *pdev, int drv_strength; int ret; - ret = device_property_read_u32(dev, "ti,trm-icp", - &sdhci_am654->trm_icp); - if (ret) - return ret; - ret = device_property_read_u32(dev, "ti,otap-del-sel", &sdhci_am654->otap_del_sel); if (ret) return ret; - ret = device_property_read_u32(dev, "ti,driver-strength-ohm", - &drv_strength); - if (ret) - return ret; + if (sdhci_am654->flags & DLL_PRESENT) { + ret = device_property_read_u32(dev, "ti,trm-icp", + &sdhci_am654->trm_icp); + if (ret) + return ret; + + ret = device_property_read_u32(dev, "ti,driver-strength-ohm", + &drv_strength); + if (ret) + return ret; - switch (drv_strength) { - case 50: - sdhci_am654->drv_strength = DRIVER_STRENGTH_50_OHM; - break; - case 33: - sdhci_am654->drv_strength = DRIVER_STRENGTH_33_OHM; - break; - case 66: - sdhci_am654->drv_strength = DRIVER_STRENGTH_66_OHM; - break; - case 100: - sdhci_am654->drv_strength = DRIVER_STRENGTH_100_OHM; - break; - case 40: - sdhci_am654->drv_strength = DRIVER_STRENGTH_40_OHM; - break; - default: - dev_err(dev, "Invalid driver strength\n"); - return -EINVAL; + switch (drv_strength) { + case 50: + sdhci_am654->drv_strength = DRIVER_STRENGTH_50_OHM; + break; + case 33: + sdhci_am654->drv_strength = DRIVER_STRENGTH_33_OHM; + break; + case 66: + sdhci_am654->drv_strength = DRIVER_STRENGTH_66_OHM; + break; + case 100: + sdhci_am654->drv_strength = DRIVER_STRENGTH_100_OHM; + break; + case 40: + sdhci_am654->drv_strength = DRIVER_STRENGTH_40_OHM; + break; + default: + dev_err(dev, "Invalid driver strength\n"); + return -EINVAL; + } } device_property_read_u32(dev, "ti,strobe-sel", &sdhci_am654->strb_sel); @@ -363,6 +407,10 @@ static const struct of_device_id sdhci_am654_of_match[] = { .compatible = "ti,j721e-sdhci-8bit", .data = &sdhci_j721e_8bit_drvdata, }, + { + .compatible = "ti,j721e-sdhci-4bit", + .data = &sdhci_j721e_4bit_drvdata, + }, { /* sentinel */ } }; -- cgit v1.2.3-59-g8ed1b From a04c50aaa916f8c5704ef8292928095ccb4469b6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 12 Jun 2019 10:25:28 +0200 Subject: mmc: core: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Ulf Hansson --- drivers/mmc/core/debugfs.c | 56 +++++++-------------------------------------- drivers/mmc/core/mmc_test.c | 10 +------- 2 files changed, 9 insertions(+), 57 deletions(-) diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index d2275c5a2311..cc3be259bc42 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c @@ -230,45 +230,21 @@ void mmc_add_host_debugfs(struct mmc_host *host) struct dentry *root; root = debugfs_create_dir(mmc_hostname(host), NULL); - if (IS_ERR(root)) - /* Don't complain -- debugfs just isn't enabled */ - return; - if (!root) - /* Complain -- debugfs is enabled, but it failed to - * create the directory. */ - goto err_root; - host->debugfs_root = root; - if (!debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops)) - goto err_node; - - if (!debugfs_create_x32("caps", S_IRUSR, root, &host->caps)) - goto err_node; - - if (!debugfs_create_x32("caps2", S_IRUSR, root, &host->caps2)) - goto err_node; - - if (!debugfs_create_file("clock", S_IRUSR | S_IWUSR, root, host, - &mmc_clock_fops)) - goto err_node; + debugfs_create_file("ios", S_IRUSR, root, host, &mmc_ios_fops); + debugfs_create_x32("caps", S_IRUSR, root, &host->caps); + debugfs_create_x32("caps2", S_IRUSR, root, &host->caps2); + debugfs_create_file("clock", S_IRUSR | S_IWUSR, root, host, + &mmc_clock_fops); #ifdef CONFIG_FAIL_MMC_REQUEST if (fail_request) setup_fault_attr(&fail_default_attr, fail_request); host->fail_mmc_request = fail_default_attr; - if (IS_ERR(fault_create_debugfs_attr("fail_mmc_request", - root, - &host->fail_mmc_request))) - goto err_node; + fault_create_debugfs_attr("fail_mmc_request", root, + &host->fail_mmc_request); #endif - return; - -err_node: - debugfs_remove_recursive(root); - host->debugfs_root = NULL; -err_root: - dev_err(&host->class_dev, "failed to initialize debugfs\n"); } void mmc_remove_host_debugfs(struct mmc_host *host) @@ -285,25 +261,9 @@ void mmc_add_card_debugfs(struct mmc_card *card) return; root = debugfs_create_dir(mmc_card_id(card), host->debugfs_root); - if (IS_ERR(root)) - /* Don't complain -- debugfs just isn't enabled */ - return; - if (!root) - /* Complain -- debugfs is enabled, but it failed to - * create the directory. */ - goto err; - card->debugfs_root = root; - if (!debugfs_create_x32("state", S_IRUSR, root, &card->state)) - goto err; - - return; - -err: - debugfs_remove_recursive(root); - card->debugfs_root = NULL; - dev_err(&card->dev, "failed to initialize debugfs\n"); + debugfs_create_x32("state", S_IRUSR, root, &card->state); } void mmc_remove_card_debugfs(struct mmc_card *card) diff --git a/drivers/mmc/core/mmc_test.c b/drivers/mmc/core/mmc_test.c index b27df2d2b5ae..492dd4596314 100644 --- a/drivers/mmc/core/mmc_test.c +++ b/drivers/mmc/core/mmc_test.c @@ -3167,15 +3167,7 @@ static int __mmc_test_register_dbgfs_file(struct mmc_card *card, struct mmc_test_dbgfs_file *df; if (card->debugfs_root) - file = debugfs_create_file(name, mode, card->debugfs_root, - card, fops); - - if (IS_ERR_OR_NULL(file)) { - dev_err(&card->dev, - "Can't create %s. Perhaps debugfs is disabled.\n", - name); - return -ENODEV; - } + debugfs_create_file(name, mode, card->debugfs_root, card, fops); df = kmalloc(sizeof(*df), GFP_KERNEL); if (!df) { -- cgit v1.2.3-59-g8ed1b From 091eb12f62b06bcf7e7cf4e4ae55e1d5ab2c25e3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 12 Jun 2019 10:25:29 +0200 Subject: mmc: host: atmel-mci: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Cc: Nicolas Ferre Signed-off-by: Greg Kroah-Hartman Acked-by: Alexandre Belloni Acked-by: Ludovic Desroches Signed-off-by: Ulf Hansson --- drivers/mmc/host/atmel-mci.c | 38 +++++++------------------------------- 1 file changed, 7 insertions(+), 31 deletions(-) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 735aa5871358..e1f10c3fa144 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -579,42 +579,18 @@ static void atmci_init_debugfs(struct atmel_mci_slot *slot) struct mmc_host *mmc = slot->mmc; struct atmel_mci *host = slot->host; struct dentry *root; - struct dentry *node; root = mmc->debugfs_root; if (!root) return; - node = debugfs_create_file("regs", S_IRUSR, root, host, - &atmci_regs_fops); - if (IS_ERR(node)) - return; - if (!node) - goto err; - - node = debugfs_create_file("req", S_IRUSR, root, slot, - &atmci_req_fops); - if (!node) - goto err; - - node = debugfs_create_u32("state", S_IRUSR, root, (u32 *)&host->state); - if (!node) - goto err; - - node = debugfs_create_x32("pending_events", S_IRUSR, root, - (u32 *)&host->pending_events); - if (!node) - goto err; - - node = debugfs_create_x32("completed_events", S_IRUSR, root, - (u32 *)&host->completed_events); - if (!node) - goto err; - - return; - -err: - dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n"); + debugfs_create_file("regs", S_IRUSR, root, host, &atmci_regs_fops); + debugfs_create_file("req", S_IRUSR, root, slot, &atmci_req_fops); + debugfs_create_u32("state", S_IRUSR, root, (u32 *)&host->state); + debugfs_create_x32("pending_events", S_IRUSR, root, + (u32 *)&host->pending_events); + debugfs_create_x32("completed_events", S_IRUSR, root, + (u32 *)&host->completed_events); } #if defined(CONFIG_OF) -- cgit v1.2.3-59-g8ed1b From fcac152782e302a553c6d197d5fb38224b50023e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 12 Jun 2019 10:25:30 +0200 Subject: mmc: host: dw_mmc: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this Cc: Jaehoon Chung Signed-off-by: Greg Kroah-Hartman Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc.c | 36 +++++++----------------------------- 1 file changed, 7 insertions(+), 29 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index b53b6b7d4dd4..faaaf52a46d2 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -169,40 +169,18 @@ static void dw_mci_init_debugfs(struct dw_mci_slot *slot) struct mmc_host *mmc = slot->mmc; struct dw_mci *host = slot->host; struct dentry *root; - struct dentry *node; root = mmc->debugfs_root; if (!root) return; - node = debugfs_create_file("regs", S_IRUSR, root, host, - &dw_mci_regs_fops); - if (!node) - goto err; - - node = debugfs_create_file("req", S_IRUSR, root, slot, - &dw_mci_req_fops); - if (!node) - goto err; - - node = debugfs_create_u32("state", S_IRUSR, root, (u32 *)&host->state); - if (!node) - goto err; - - node = debugfs_create_x32("pending_events", S_IRUSR, root, - (u32 *)&host->pending_events); - if (!node) - goto err; - - node = debugfs_create_x32("completed_events", S_IRUSR, root, - (u32 *)&host->completed_events); - if (!node) - goto err; - - return; - -err: - dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n"); + debugfs_create_file("regs", S_IRUSR, root, host, &dw_mci_regs_fops); + debugfs_create_file("req", S_IRUSR, root, slot, &dw_mci_req_fops); + debugfs_create_u32("state", S_IRUSR, root, (u32 *)&host->state); + debugfs_create_x32("pending_events", S_IRUSR, root, + (u32 *)&host->pending_events); + debugfs_create_x32("completed_events", S_IRUSR, root, + (u32 *)&host->completed_events); } #endif /* defined(CONFIG_DEBUG_FS) */ -- cgit v1.2.3-59-g8ed1b From 5928d8929d8cc3ba89f0af57ddeecaa004aa2340 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 12 Jun 2019 10:25:31 +0200 Subject: mmc: host: s3cmci: no need to check return value of debugfs_create functions When calling debugfs functions, there is no need to ever check the return value. The function can work or not, but the code logic should never do something different based on this. Also, because there is no need to save the file dentries, remove them from the host-specific structure and just recursively delete the directory that the driver created, when shutting down. Cc: Ben Dooks Signed-off-by: Greg Kroah-Hartman Signed-off-by: Ulf Hansson --- drivers/mmc/host/s3cmci.c | 27 ++++++--------------------- drivers/mmc/host/s3cmci.h | 2 -- 2 files changed, 6 insertions(+), 23 deletions(-) diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index f31333e831a7..6a91db7ca5f1 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -1452,33 +1452,18 @@ DEFINE_SHOW_ATTRIBUTE(s3cmci_regs); static void s3cmci_debugfs_attach(struct s3cmci_host *host) { struct device *dev = &host->pdev->dev; + struct dentry *root; - host->debug_root = debugfs_create_dir(dev_name(dev), NULL); - if (IS_ERR(host->debug_root)) { - dev_err(dev, "failed to create debugfs root\n"); - return; - } - - host->debug_state = debugfs_create_file("state", 0444, - host->debug_root, host, - &s3cmci_state_fops); - - if (IS_ERR(host->debug_state)) - dev_err(dev, "failed to create debug state file\n"); - - host->debug_regs = debugfs_create_file("regs", 0444, - host->debug_root, host, - &s3cmci_regs_fops); + root = debugfs_create_dir(dev_name(dev), NULL); + host->debug_root = root; - if (IS_ERR(host->debug_regs)) - dev_err(dev, "failed to create debug regs file\n"); + debugfs_create_file("state", 0444, root, host, &s3cmci_state_fops); + debugfs_create_file("regs", 0444, root, host, &s3cmci_regs_fops); } static void s3cmci_debugfs_remove(struct s3cmci_host *host) { - debugfs_remove(host->debug_regs); - debugfs_remove(host->debug_state); - debugfs_remove(host->debug_root); + debugfs_remove_recursive(host->debug_root); } #else diff --git a/drivers/mmc/host/s3cmci.h b/drivers/mmc/host/s3cmci.h index 30c2c0dd1bc8..62cae53b4271 100644 --- a/drivers/mmc/host/s3cmci.h +++ b/drivers/mmc/host/s3cmci.h @@ -70,8 +70,6 @@ struct s3cmci_host { #ifdef CONFIG_DEBUG_FS struct dentry *debug_root; - struct dentry *debug_state; - struct dentry *debug_regs; #endif #ifdef CONFIG_ARM_S3C24XX_CPUFREQ -- cgit v1.2.3-59-g8ed1b From 04509d77097914ae1bd351f4cec751d011844ca3 Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Fri, 14 Jun 2019 16:29:53 +0800 Subject: mmc: sdhci-of-esdhc: set the sd clock divisor value above 3 This patch is to set the sd clock divisor value above 3 in tuning mode Signed-off-by: Yinbo Zhu Signed-off-by: Yangbo Lu Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-esdhc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 68c5866f5c85..c56c7d413a09 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -830,9 +830,17 @@ static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host); bool hs400_tuning; + unsigned int clk; u32 val; int ret; + /* For tuning mode, the sd clock divisor value + * must be larger than 3 according to reference manual. + */ + clk = esdhc->peripheral_clock / 3; + if (host->clock > clk) + esdhc_of_set_clock(host, clk); + if (esdhc->quirk_limited_clk_division && host->flags & SDHCI_HS400_TUNING) esdhc_of_set_clock(host, host->clock); -- cgit v1.2.3-59-g8ed1b From 791463ba1ae90a7457ddcb07c6c5a1a64738e354 Mon Sep 17 00:00:00 2001 From: Yangbo Lu Date: Fri, 14 Jun 2019 16:29:54 +0800 Subject: mmc: sdhci-of-esdhc: use 1/2 periperhal clock for ls1028a LS1028A used 1/2 periperhal clock as one reference clock. Signed-off-by: Yangbo Lu Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-of-esdhc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index c56c7d413a09..4dd43b1adf2c 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -1048,11 +1048,12 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host) /* * esdhc->peripheral_clock would be assigned with a value * which is eSDHC base clock when use periperal clock. - * For ls1046a, the clock value got by common clk API is - * peripheral clock while the eSDHC base clock is 1/2 - * peripheral clock. + * For some platforms, the clock value got by common clk + * API is peripheral clock while the eSDHC base clock is + * 1/2 peripheral clock. */ - if (of_device_is_compatible(np, "fsl,ls1046a-esdhc")) + if (of_device_is_compatible(np, "fsl,ls1046a-esdhc") || + of_device_is_compatible(np, "fsl,ls1028a-esdhc")) esdhc->peripheral_clock = clk_get_rate(clk) / 2; else esdhc->peripheral_clock = clk_get_rate(clk); -- cgit v1.2.3-59-g8ed1b From de23f0b757766d9fae59df97da6e8bdc5b231351 Mon Sep 17 00:00:00 2001 From: Raul E Rangel Date: Mon, 17 Jun 2019 14:10:13 -0600 Subject: mmc: sdhci: sdhci-pci-o2micro: Check if controller supports 8-bit width The O2 controller supports 8-bit EMMC access. JESD84-B51 section A.6.3.a defines the bus testing procedure that `mmc_select_bus_width()` implements. This is used to determine the actual bus width of the eMMC. Signed-off-by: Raul E Rangel Acked-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pci-o2micro.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c index dd21315922c8..9dc4548271b4 100644 --- a/drivers/mmc/host/sdhci-pci-o2micro.c +++ b/drivers/mmc/host/sdhci-pci-o2micro.c @@ -395,11 +395,21 @@ int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) { struct sdhci_pci_chip *chip; struct sdhci_host *host; - u32 reg; + u32 reg, caps; int ret; chip = slot->chip; host = slot->host; + + caps = sdhci_readl(host, SDHCI_CAPABILITIES); + + /* + * mmc_select_bus_width() will test the bus to determine the actual bus + * width. + */ + if (caps & SDHCI_CAN_DO_8BIT) + host->mmc->caps |= MMC_CAP_8_BIT_DATA; + switch (chip->pdev->device) { case PCI_DEVICE_ID_O2_SDS0: case PCI_DEVICE_ID_O2_SEABIRD0: -- cgit v1.2.3-59-g8ed1b From 6e8e1acda6aab9638c15c085dbef1dc429c1e87e Mon Sep 17 00:00:00 2001 From: Raul E Rangel Date: Mon, 17 Jun 2019 14:10:14 -0600 Subject: mmc: sdhci: Fix indenting on SDHCI_CTRL_8BITBUS Remove whitespace in front of SDHCI_CTRL_8BITBUS. The value is not part of SDHCI_CTRL_DMA_MASK. Signed-off-by: Raul E Rangel Acked-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 199712e7adbb..89fd96596a1f 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -89,7 +89,7 @@ #define SDHCI_CTRL_ADMA32 0x10 #define SDHCI_CTRL_ADMA64 0x18 #define SDHCI_CTRL_ADMA3 0x18 -#define SDHCI_CTRL_8BITBUS 0x20 +#define SDHCI_CTRL_8BITBUS 0x20 #define SDHCI_CTRL_CDTEST_INS 0x40 #define SDHCI_CTRL_CDTEST_EN 0x80 -- cgit v1.2.3-59-g8ed1b From cf4b20ecfa4edc4a0e55d52bc0a735f60bdfe7eb Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 18 Jun 2019 17:34:42 +0200 Subject: mmc: sdio: Turn sdio_run_irqs() into static All external users of sdio_run_irqs() have converted into using the preferred sdio_signal_irq() interface, thus not calling the function directly any more. Avoid further new users of it, by turning it into static. Suggested-by: Douglas Anderson Signed-off-by: Ulf Hansson Reviewed-by: Douglas Anderson Signed-off-by: Ulf Hansson --- drivers/mmc/core/sdio_irq.c | 3 +-- include/linux/mmc/host.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index 9f54a259a1b3..0bcc5e83bd1a 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c @@ -92,7 +92,7 @@ static int process_sdio_pending_irqs(struct mmc_host *host) return ret; } -void sdio_run_irqs(struct mmc_host *host) +static void sdio_run_irqs(struct mmc_host *host) { mmc_claim_host(host); if (host->sdio_irqs) { @@ -103,7 +103,6 @@ void sdio_run_irqs(struct mmc_host *host) } mmc_release_host(host); } -EXPORT_SYMBOL_GPL(sdio_run_irqs); void sdio_irq_work(struct work_struct *work) { diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index ecb7972e2423..a9b12322c775 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -504,7 +504,6 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host) wake_up_process(host->sdio_irq_thread); } -void sdio_run_irqs(struct mmc_host *host); void sdio_signal_irq(struct mmc_host *host); #ifdef CONFIG_REGULATOR -- cgit v1.2.3-59-g8ed1b From cd23042d05468ab2e66e0298b46ee90a5f8d9a74 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 11 Jun 2019 17:44:32 +0200 Subject: mmc: sdio: Drop mmc_claim|release_host() in mmc_sdio_power_restore() The function mmc_sdio_power_restore() is called either from mmc_sdio_runtime_resume() or from mmc_sdio_hw_reset(). Both callers either claims/releases the host or require its callers to do so. Therefore let's drop the redundant calls to mmc_claim|release_host() in mmc_sdio_power_restore(). Signed-off-by: Ulf Hansson Reviewed-by: Douglas Anderson Tested-by: Douglas Anderson --- drivers/mmc/core/sdio.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 712a7742765e..b3303b7d9956 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -1030,14 +1030,10 @@ static int mmc_sdio_power_restore(struct mmc_host *host) * */ - mmc_claim_host(host); - ret = mmc_sdio_reinit_card(host, mmc_card_keep_power(host)); if (!ret && host->sdio_irqs) mmc_signal_sdio_irq(host); - mmc_release_host(host); - return ret; } -- cgit v1.2.3-59-g8ed1b From ee550947a0d696f7ddfe88b204d4eae7f879b583 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 17 Jun 2019 23:41:15 +0200 Subject: mmc: sdio: Move comment about re-initialization to mmc_sdio_reinit_card() The comment in mmc_sdio_power_restore() belongs in mmc_sdio_reinit_card(), which was created during a previous commit that re-factored some code. Fix this by moving the comment into mmc_sdio_reinit_card(). Signed-off-by: Ulf Hansson Reviewed-by: Douglas Anderson --- drivers/mmc/core/sdio.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index b3303b7d9956..29f86c1e9923 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -820,6 +820,23 @@ static int mmc_sdio_reinit_card(struct mmc_host *host, bool powered_resume) { int ret; + /* + * Reset the card by performing the same steps that are taken by + * mmc_rescan_try_freq() and mmc_attach_sdio() during a "normal" probe. + * + * sdio_reset() is technically not needed. Having just powered up the + * hardware, it should already be in reset state. However, some + * platforms (such as SD8686 on OLPC) do not instantly cut power, + * meaning that a reset is required when restoring power soon after + * powering off. It is harmless in other cases. + * + * The CMD5 reset (mmc_send_io_op_cond()), according to the SDIO spec, + * is not necessary for non-removable cards. However, it is required + * for OLPC SD8686 (which expects a [CMD5,5,3,7] init sequence), and + * harmless in other situations. + * + */ + sdio_reset(host); mmc_go_idle(host); mmc_send_if_cond(host, host->card->ocr); @@ -1013,23 +1030,6 @@ static int mmc_sdio_power_restore(struct mmc_host *host) { int ret; - /* - * Reset the card by performing the same steps that are taken by - * mmc_rescan_try_freq() and mmc_attach_sdio() during a "normal" probe. - * - * sdio_reset() is technically not needed. Having just powered up the - * hardware, it should already be in reset state. However, some - * platforms (such as SD8686 on OLPC) do not instantly cut power, - * meaning that a reset is required when restoring power soon after - * powering off. It is harmless in other cases. - * - * The CMD5 reset (mmc_send_io_op_cond()), according to the SDIO spec, - * is not necessary for non-removable cards. However, it is required - * for OLPC SD8686 (which expects a [CMD5,5,3,7] init sequence), and - * harmless in other situations. - * - */ - ret = mmc_sdio_reinit_card(host, mmc_card_keep_power(host)); if (!ret && host->sdio_irqs) mmc_signal_sdio_irq(host); -- cgit v1.2.3-59-g8ed1b From 7fbbe725378d62c30a076742a60a7e1812a2515a Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Mon, 17 Jun 2019 23:51:31 +0200 Subject: mmc: sdio: Drop powered-on re-init at runtime resume and HW reset To use the so called powered-on re-initialization of an SDIO card, the power to the card must obviously have stayed on. If not, the initialization will simply fail. In the runtime suspend case, the card is always powered off. Hence, let's drop the support for powered-on re-initialization during runtime resume, as it doesn't make sense. Moreover, during a HW reset, the point is to cut the power to the card and then do fresh re-initialization. Therefore drop the support for powered-on re-initialization during HW reset. Signed-off-by: Ulf Hansson Fixes: ca8971ca5753 ("mmc: dw_mmc: Prevent runtime PM suspend when SDIO IRQs are enabled") Tested-by: Douglas Anderson --- drivers/mmc/core/sdio.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 29f86c1e9923..a9bfcae8db5b 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -1028,13 +1028,7 @@ out: static int mmc_sdio_power_restore(struct mmc_host *host) { - int ret; - - ret = mmc_sdio_reinit_card(host, mmc_card_keep_power(host)); - if (!ret && host->sdio_irqs) - mmc_signal_sdio_irq(host); - - return ret; + return mmc_sdio_reinit_card(host, 0); } static int mmc_sdio_runtime_suspend(struct mmc_host *host) -- cgit v1.2.3-59-g8ed1b From 6ebc581c3f9e6fd11a1c9da492a5e05bbe96885a Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 18 Jun 2019 00:52:59 +0200 Subject: mmc: sdio: Don't re-initialize powered-on removable SDIO cards at resume It looks like the original idea behind always doing a re-initialization of a removable SDIO card during system resume in mmc_sdio_resume(), is to try to play safe to detect whether the card has been removed. However, this seems like a really a bad idea as it will most likely screw things up, especially when the card is expected to remain powered on during system suspend by the SDIO func driver. Let's fix this, simply by trusting that the detect work checks if the card is alive and inserted, which is being scheduled at the PM_POST_SUSPEND notification anyway. Signed-off-by: Ulf Hansson Tested-by: Douglas Anderson Reviewed-by: Douglas Anderson --- drivers/mmc/core/sdio.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index a9bfcae8db5b..945416c53b56 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -982,7 +982,11 @@ static int mmc_sdio_resume(struct mmc_host *host) /* Basic card reinitialization. */ mmc_claim_host(host); - /* Restore power if needed */ + /* + * Restore power and reinitialize the card when needed. Note that a + * removable card is checked from a detect work later on in the resume + * process. + */ if (!mmc_card_keep_power(host)) { mmc_power_up(host, host->card->ocr); /* @@ -996,12 +1000,8 @@ static int mmc_sdio_resume(struct mmc_host *host) pm_runtime_set_active(&host->card->dev); pm_runtime_enable(&host->card->dev); } - } - - /* No need to reinitialize powered-resumed nonremovable cards */ - if (mmc_card_is_removable(host) || !mmc_card_keep_power(host)) { - err = mmc_sdio_reinit_card(host, mmc_card_keep_power(host)); - } else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) { + err = mmc_sdio_reinit_card(host, 0); + } else if (mmc_card_wake_sdio_irq(host)) { /* We may have switched to 1-bit mode during suspend */ err = sdio_enable_4bit_bus(host->card); } -- cgit v1.2.3-59-g8ed1b From 3c30e73977e5d1a14a2969cfebcca2655a29b40a Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 18 Jun 2019 01:13:02 +0200 Subject: mmc: sdio: Drop unused in-parameter to mmc_sdio_reinit_card() The "powered_resume" in-parameter to mmc_sdio_reinit_card() has now become redundant as all callers set it to 0. Therefore let's just drop it. Signed-off-by: Ulf Hansson Reviewed-by: Douglas Anderson Tested-by: Douglas Anderson --- drivers/mmc/core/sdio.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 945416c53b56..0bf603670f61 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -816,7 +816,7 @@ err: return err; } -static int mmc_sdio_reinit_card(struct mmc_host *host, bool powered_resume) +static int mmc_sdio_reinit_card(struct mmc_host *host) { int ret; @@ -845,8 +845,7 @@ static int mmc_sdio_reinit_card(struct mmc_host *host, bool powered_resume) if (ret) return ret; - return mmc_sdio_init_card(host, host->card->ocr, host->card, - powered_resume); + return mmc_sdio_init_card(host, host->card->ocr, host->card, 0); } /* @@ -1000,7 +999,7 @@ static int mmc_sdio_resume(struct mmc_host *host) pm_runtime_set_active(&host->card->dev); pm_runtime_enable(&host->card->dev); } - err = mmc_sdio_reinit_card(host, 0); + err = mmc_sdio_reinit_card(host); } else if (mmc_card_wake_sdio_irq(host)) { /* We may have switched to 1-bit mode during suspend */ err = sdio_enable_4bit_bus(host->card); @@ -1026,11 +1025,6 @@ out: return err; } -static int mmc_sdio_power_restore(struct mmc_host *host) -{ - return mmc_sdio_reinit_card(host, 0); -} - static int mmc_sdio_runtime_suspend(struct mmc_host *host) { /* No references to the card, cut the power to it. */ @@ -1048,7 +1042,7 @@ static int mmc_sdio_runtime_resume(struct mmc_host *host) /* Restore power and re-initialize. */ mmc_claim_host(host); mmc_power_up(host, host->card->ocr); - ret = mmc_sdio_power_restore(host); + ret = mmc_sdio_reinit_card(host); mmc_release_host(host); return ret; @@ -1057,7 +1051,7 @@ static int mmc_sdio_runtime_resume(struct mmc_host *host) static int mmc_sdio_hw_reset(struct mmc_host *host) { mmc_power_cycle(host, host->card->ocr); - return mmc_sdio_power_restore(host); + return mmc_sdio_reinit_card(host); } static int mmc_sdio_sw_reset(struct mmc_host *host) @@ -1069,7 +1063,7 @@ static int mmc_sdio_sw_reset(struct mmc_host *host) mmc_set_initial_state(host); mmc_set_initial_signal_voltage(host); - return mmc_sdio_reinit_card(host, 0); + return mmc_sdio_reinit_card(host); } static const struct mmc_bus_ops mmc_sdio_ops = { -- cgit v1.2.3-59-g8ed1b From 4aaaf3ab150947557345aedc178dac4f5c10cc87 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 18 Jun 2019 01:20:50 +0200 Subject: mmc: sdio: Drop unused in-parameter from mmc_sdio_init_card() The "powered_resume" in-parameter to mmc_sdio_init_card() has now become redundant as all callers set it to 0. Therefore let's just drop it. Signed-off-by: Ulf Hansson Reviewed-by: Douglas Anderson Tested-by: Douglas Anderson --- drivers/mmc/core/sdio.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 0bf603670f61..8dd8fc32ecca 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -559,7 +559,7 @@ static void mmc_sdio_resend_if_cond(struct mmc_host *host, * we're trying to reinitialise. */ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, - struct mmc_card *oldcard, int powered_resume) + struct mmc_card *oldcard) { struct mmc_card *card; int err; @@ -582,11 +582,9 @@ try_again: /* * Inform the card of the voltage */ - if (!powered_resume) { - err = mmc_send_io_op_cond(host, ocr, &rocr); - if (err) - goto err; - } + err = mmc_send_io_op_cond(host, ocr, &rocr); + if (err) + goto err; /* * For SPI, enable CRC as appropriate. @@ -645,7 +643,7 @@ try_again: * try to init uhs card. sdio_read_cccr will take over this task * to make sure which speed mode should work. */ - if (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) { + if (rocr & ocr & R4_18V_PRESENT) { err = mmc_set_uhs_voltage(host, ocr_card); if (err == -EAGAIN) { mmc_sdio_resend_if_cond(host, card); @@ -659,7 +657,7 @@ try_again: /* * For native busses: set card RCA and quit open drain mode. */ - if (!powered_resume && !mmc_host_is_spi(host)) { + if (!mmc_host_is_spi(host)) { err = mmc_send_relative_addr(host, &card->rca); if (err) goto remove; @@ -687,7 +685,7 @@ try_again: /* * Select card, as all following commands rely on that. */ - if (!powered_resume && !mmc_host_is_spi(host)) { + if (!mmc_host_is_spi(host)) { err = mmc_select_card(card); if (err) goto remove; @@ -845,7 +843,7 @@ static int mmc_sdio_reinit_card(struct mmc_host *host) if (ret) return ret; - return mmc_sdio_init_card(host, host->card->ocr, host->card, 0); + return mmc_sdio_init_card(host, host->card->ocr, host->card); } /* @@ -1113,7 +1111,7 @@ int mmc_attach_sdio(struct mmc_host *host) /* * Detect and init the card. */ - err = mmc_sdio_init_card(host, rocr, NULL, 0); + err = mmc_sdio_init_card(host, rocr, NULL); if (err) goto err; -- cgit v1.2.3-59-g8ed1b From 63624d13b24d00fa3783181efdfdb9d5afaa7363 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 19 Jun 2019 13:55:30 +0900 Subject: mmc: tmio: Use dma_max_mapping_size() instead of a workaround Since the commit 133d624b1cee ("dma: Introduce dma_max_mapping_size()") provides a helper function to get the max mapping size, we can use the function instead of the workaround code for swiotlb. Signed-off-by: Yoshihiro Shimoda Acked-by: Wolfram Sang Reviewed-by: Christoph Hellwig Reviewed-by: Geert Uytterhoeven Reviewed-by: Simon Horman Signed-off-by: Ulf Hansson --- drivers/mmc/host/tmio_mmc_core.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index 83fd94341113..2cb3f951c3e2 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -45,7 +46,6 @@ #include #include #include -#include #include #include "tmio_mmc.h" @@ -1199,19 +1199,9 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) mmc->max_blk_size = TMIO_MAX_BLK_SIZE; mmc->max_blk_count = pdata->max_blk_count ? : (PAGE_SIZE / mmc->max_blk_size) * mmc->max_segs; - mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; - /* - * Since swiotlb has memory size limitation, this will calculate - * the maximum size locally (because we don't have any APIs for it now) - * and check the current max_req_size. And then, this will update - * the max_req_size if needed as a workaround. - */ - if (swiotlb_max_segment()) { - unsigned int max_size = (1 << IO_TLB_SHIFT) * IO_TLB_SEGSIZE; - - if (mmc->max_req_size > max_size) - mmc->max_req_size = max_size; - } + mmc->max_req_size = min_t(size_t, + mmc->max_blk_size * mmc->max_blk_count, + dma_max_mapping_size(&pdev->dev)); mmc->max_seg_size = mmc->max_req_size; if (mmc_can_gpio_ro(mmc)) -- cgit v1.2.3-59-g8ed1b From cb3a7d4a0aec4e56043d6433724e0606d6b6efba Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 20 Jun 2019 12:49:01 +0300 Subject: mmc: sdhci-pci: Add support for Intel EHL Add PCI Ids for Intel EHL. Signed-off-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-pci-core.c | 2 ++ drivers/mmc/host/sdhci-pci.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index fa6a8fa560c3..4041878eb0f3 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -1668,6 +1668,8 @@ static const struct pci_device_id pci_ids[] = { SDHCI_PCI_DEVICE(INTEL, CNPH_SD, intel_byt_sd), SDHCI_PCI_DEVICE(INTEL, ICP_EMMC, intel_glk_emmc), SDHCI_PCI_DEVICE(INTEL, ICP_SD, intel_byt_sd), + SDHCI_PCI_DEVICE(INTEL, EHL_EMMC, intel_glk_emmc), + SDHCI_PCI_DEVICE(INTEL, EHL_SD, intel_byt_sd), SDHCI_PCI_DEVICE(INTEL, CML_EMMC, intel_glk_emmc), SDHCI_PCI_DEVICE(INTEL, CML_SD, intel_byt_sd), SDHCI_PCI_DEVICE(O2, 8120, o2), diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h index e5dc6e44c7a4..cdd15f357d01 100644 --- a/drivers/mmc/host/sdhci-pci.h +++ b/drivers/mmc/host/sdhci-pci.h @@ -50,6 +50,8 @@ #define PCI_DEVICE_ID_INTEL_CNPH_SD 0xa375 #define PCI_DEVICE_ID_INTEL_ICP_EMMC 0x34c4 #define PCI_DEVICE_ID_INTEL_ICP_SD 0x34f8 +#define PCI_DEVICE_ID_INTEL_EHL_EMMC 0x4b47 +#define PCI_DEVICE_ID_INTEL_EHL_SD 0x4b48 #define PCI_DEVICE_ID_INTEL_CML_EMMC 0x02c4 #define PCI_DEVICE_ID_INTEL_CML_SD 0x02f5 -- cgit v1.2.3-59-g8ed1b From eef9e0a60e78be6873b515e85466cac2f25581ed Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Fri, 21 Jun 2019 14:12:31 +0800 Subject: mmc: sdhci-sprd: Add start_signal_voltage_switch ops For Spreadtrum SD host controller, we can not use standard SD registers to change and detect the I/O voltage signals, since our voltage regulator for I/O is fixed in hardware, and no signals were connected to the SD controller. Thus add Spreadtrum specific voltage switch ops to change voltage instead of using standard SD host registers. Signed-off-by: Baolin Wang Acked-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-sprd.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index 024c3c5fa979..8b23c8838fb9 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -403,6 +403,22 @@ static void sdhci_sprd_request(struct mmc_host *mmc, struct mmc_request *mrq) sdhci_request(mmc, mrq); } +static int sdhci_sprd_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios) +{ + int ret; + + if (!IS_ERR(mmc->supply.vqmmc)) { + ret = mmc_regulator_set_vqmmc(mmc, ios); + if (ret) { + pr_err("%s: Switching signalling voltage failed\n", + mmc_hostname(mmc)); + return ret; + } + } + + return 0; +} + static void sdhci_sprd_hs400_enhanced_strobe(struct mmc_host *mmc, struct mmc_ios *ios) { @@ -470,6 +486,14 @@ static int sdhci_sprd_probe(struct platform_device *pdev) host->mmc_host_ops.request = sdhci_sprd_request; host->mmc_host_ops.hs400_enhanced_strobe = sdhci_sprd_hs400_enhanced_strobe; + /* + * We can not use the standard ops to change and detect the voltage + * signal for Spreadtrum SD host controller, since our voltage regulator + * for I/O is fixed in hardware, that means we do not need control + * the standard SD host controller to change the I/O voltage. + */ + host->mmc_host_ops.start_signal_voltage_switch = + sdhci_sprd_voltage_switch; host->mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_ERASE | MMC_CAP_CMD23; -- cgit v1.2.3-59-g8ed1b From f97ee8f5d9cdd03933517a6336836b8e4415e668 Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Fri, 21 Jun 2019 14:12:32 +0800 Subject: dt-bindings: mmc: sprd: Add pinctrl support When changing SD card voltage signal for Spreadtrum SD host controller, it also need to switch related pin's state. Thus add pinctrl properties' description in documentation. Signed-off-by: Baolin Wang Signed-off-by: Ulf Hansson --- Documentation/devicetree/bindings/mmc/sdhci-sprd.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/sdhci-sprd.txt b/Documentation/devicetree/bindings/mmc/sdhci-sprd.txt index e675397fa428..eb7eb1b529f0 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-sprd.txt +++ b/Documentation/devicetree/bindings/mmc/sdhci-sprd.txt @@ -19,6 +19,9 @@ Required properties: Optional properties: - assigned-clocks: the same with "sdio" clock - assigned-clock-parents: the default parent of "sdio" clock +- pinctrl-names: should be "default", "state_uhs" +- pinctrl-0: should contain default/high speed pin control +- pinctrl-1: should contain uhs mode pin control PHY DLL delays are used to delay the data valid window, and align the window to sampling clock. PHY DLL delays can be configured by following properties, @@ -50,6 +53,10 @@ sdio0: sdio@20600000 { assigned-clocks = <&ap_clk CLK_EMMC_2X>; assigned-clock-parents = <&rpll CLK_RPLL_390M>; + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&sd0_pins_default>; + pinctrl-1 = <&sd0_pins_uhs>; + sprd,phy-delay-sd-uhs-sdr104 = <0x3f 0x7f 0x2e 0x2e>; bus-width = <8>; non-removable; -- cgit v1.2.3-59-g8ed1b From 29ca763fc26f382444887951b3443da0fa47e5fc Mon Sep 17 00:00:00 2001 From: Baolin Wang Date: Fri, 21 Jun 2019 14:12:33 +0800 Subject: mmc: sdhci-sprd: Add pin control support for voltage switch For Spreadtrum SD card voltage switching, besides regulator setting, it also need switch related pin's state to output corresponding voltage. This patch adds pin control operation to support voltage switch. Signed-off-by: Baolin Wang Acked-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-sprd.c | 54 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index 8b23c8838fb9..6ee340a3fb3a 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +73,9 @@ struct sdhci_sprd_host { struct clk *clk_sdio; struct clk *clk_enable; struct clk *clk_2x_enable; + struct pinctrl *pinctrl; + struct pinctrl_state *pins_uhs; + struct pinctrl_state *pins_default; u32 base_rate; int flags; /* backup of host attribute */ u32 phy_delay[MMC_TIMING_MMC_HS400 + 2]; @@ -405,6 +409,8 @@ static void sdhci_sprd_request(struct mmc_host *mmc, struct mmc_request *mrq) static int sdhci_sprd_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios) { + struct sdhci_host *host = mmc_priv(mmc); + struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host); int ret; if (!IS_ERR(mmc->supply.vqmmc)) { @@ -416,6 +422,37 @@ static int sdhci_sprd_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios) } } + if (IS_ERR(sprd_host->pinctrl)) + return 0; + + switch (ios->signal_voltage) { + case MMC_SIGNAL_VOLTAGE_180: + ret = pinctrl_select_state(sprd_host->pinctrl, + sprd_host->pins_uhs); + if (ret) { + pr_err("%s: failed to select uhs pin state\n", + mmc_hostname(mmc)); + return ret; + } + break; + + default: + /* fall-through */ + case MMC_SIGNAL_VOLTAGE_330: + ret = pinctrl_select_state(sprd_host->pinctrl, + sprd_host->pins_default); + if (ret) { + pr_err("%s: failed to select default pin state\n", + mmc_hostname(mmc)); + return ret; + } + break; + } + + /* Wait for 300 ~ 500 us for pin state stable */ + usleep_range(300, 500); + sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + return 0; } @@ -504,6 +541,23 @@ static int sdhci_sprd_probe(struct platform_device *pdev) sprd_host = TO_SPRD_HOST(host); sdhci_sprd_phy_param_parse(sprd_host, pdev->dev.of_node); + sprd_host->pinctrl = devm_pinctrl_get(&pdev->dev); + if (!IS_ERR(sprd_host->pinctrl)) { + sprd_host->pins_uhs = + pinctrl_lookup_state(sprd_host->pinctrl, "state_uhs"); + if (IS_ERR(sprd_host->pins_uhs)) { + ret = PTR_ERR(sprd_host->pins_uhs); + goto pltfm_free; + } + + sprd_host->pins_default = + pinctrl_lookup_state(sprd_host->pinctrl, "default"); + if (IS_ERR(sprd_host->pins_default)) { + ret = PTR_ERR(sprd_host->pins_default); + goto pltfm_free; + } + } + clk = devm_clk_get(&pdev->dev, "sdio"); if (IS_ERR(clk)) { ret = PTR_ERR(clk); -- cgit v1.2.3-59-g8ed1b From 1cdca16c043abd4803c3979e5faefaa623703e66 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 24 Jun 2019 16:03:45 +0900 Subject: dt-binding: mmc: rename tmio_mmc.txt to renesas,sdhi.txt As commit b6147490e6aa ("mmc: tmio: split core functionality, DMA and MFD glue") said, these MMC controllers use the IP from Panasonic. TMIO (Toshiba Mobile IO) MMC was the first upstreamed user of this IP. The common driver code was split and expanded as 'tmio-mmc-core', then it became historical misnomer since 'tmio' is not the name of this IP. In the discussion [1], we decide to keep this name as-is at least in Linux driver level because renaming everything is a big churn. However, DT should not be oriented to a particular project even though it is mainly developed in Linux communities. This is the misfortune only in Linux. Let's stop exporting it to other projects, where there is no good reason to call this hardware "TMIO". Rename the file to renesas,sdhi.txt. In fact, all the information in this file is specific to the Renesas platform. This commit also removes the first paragraph entirely. The DT-binding should describe the hardware. It is strange to talk about Linux driver internals such as how the drivers are probed, how platform data are handed off, etc. [1] https://www.spinics.net/lists/linux-mmc/msg46952.html Signed-off-by: Masahiro Yamada Reviewed-by: Simon Horman Signed-off-by: Ulf Hansson --- .../devicetree/bindings/mmc/renesas,sdhi.txt | 111 +++++++++++++++++++ Documentation/devicetree/bindings/mmc/tmio_mmc.txt | 120 --------------------- 2 files changed, 111 insertions(+), 120 deletions(-) create mode 100644 Documentation/devicetree/bindings/mmc/renesas,sdhi.txt delete mode 100644 Documentation/devicetree/bindings/mmc/tmio_mmc.txt diff --git a/Documentation/devicetree/bindings/mmc/renesas,sdhi.txt b/Documentation/devicetree/bindings/mmc/renesas,sdhi.txt new file mode 100644 index 000000000000..dd08d038a65c --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/renesas,sdhi.txt @@ -0,0 +1,111 @@ +* Renesas SDHI SD/MMC controller + +Required properties: +- compatible: should contain one or more of the following: + "renesas,sdhi-sh73a0" - SDHI IP on SH73A0 SoC + "renesas,sdhi-r7s72100" - SDHI IP on R7S72100 SoC + "renesas,sdhi-r7s9210" - SDHI IP on R7S9210 SoC + "renesas,sdhi-r8a73a4" - SDHI IP on R8A73A4 SoC + "renesas,sdhi-r8a7740" - SDHI IP on R8A7740 SoC + "renesas,sdhi-r8a7743" - SDHI IP on R8A7743 SoC + "renesas,sdhi-r8a7744" - SDHI IP on R8A7744 SoC + "renesas,sdhi-r8a7745" - SDHI IP on R8A7745 SoC + "renesas,sdhi-r8a774a1" - SDHI IP on R8A774A1 SoC + "renesas,sdhi-r8a774c0" - SDHI IP on R8A774C0 SoC + "renesas,sdhi-r8a77470" - SDHI IP on R8A77470 SoC + "renesas,sdhi-mmc-r8a77470" - SDHI/MMC IP on R8A77470 SoC + "renesas,sdhi-r8a7778" - SDHI IP on R8A7778 SoC + "renesas,sdhi-r8a7779" - SDHI IP on R8A7779 SoC + "renesas,sdhi-r8a7790" - SDHI IP on R8A7790 SoC + "renesas,sdhi-r8a7791" - SDHI IP on R8A7791 SoC + "renesas,sdhi-r8a7792" - SDHI IP on R8A7792 SoC + "renesas,sdhi-r8a7793" - SDHI IP on R8A7793 SoC + "renesas,sdhi-r8a7794" - SDHI IP on R8A7794 SoC + "renesas,sdhi-r8a7795" - SDHI IP on R8A7795 SoC + "renesas,sdhi-r8a7796" - SDHI IP on R8A7796 SoC + "renesas,sdhi-r8a77965" - SDHI IP on R8A77965 SoC + "renesas,sdhi-r8a77970" - SDHI IP on R8A77970 SoC + "renesas,sdhi-r8a77980" - SDHI IP on R8A77980 SoC + "renesas,sdhi-r8a77990" - SDHI IP on R8A77990 SoC + "renesas,sdhi-r8a77995" - SDHI IP on R8A77995 SoC + "renesas,sdhi-shmobile" - a generic sh-mobile SDHI controller + "renesas,rcar-gen1-sdhi" - a generic R-Car Gen1 SDHI controller + "renesas,rcar-gen2-sdhi" - a generic R-Car Gen2 and RZ/G1 SDHI + (not SDHI/MMC) controller + "renesas,rcar-gen3-sdhi" - a generic R-Car Gen3 or RZ/G2 + SDHI controller + + + When compatible with the generic version, nodes must list + the SoC-specific version corresponding to the platform + first followed by the generic version. + +- clocks: Most controllers only have 1 clock source per channel. However, on + some variations of this controller, the internal card detection + logic that exists in this controller is sectioned off to be run by a + separate second clock source to allow the main core clock to be turned + off to save power. + If 2 clocks are specified by the hardware, you must name them as + "core" and "cd". If the controller only has 1 clock, naming is not + required. + Devices which have more than 1 clock are listed below: + 2: R7S72100, R7S9210 + +Optional properties: +- pinctrl-names: should be "default", "state_uhs" +- pinctrl-0: should contain default/high speed pin ctrl +- pinctrl-1: should contain uhs mode pin ctrl + +Example: R8A7790 (R-Car H2) SDHI controller nodes + + sdhi0: sd@ee100000 { + compatible = "renesas,sdhi-r8a7790", "renesas,rcar-gen2-sdhi"; + reg = <0 0xee100000 0 0x328>; + interrupts = ; + clocks = <&cpg CPG_MOD 314>; + dmas = <&dmac0 0xcd>, <&dmac0 0xce>, + <&dmac1 0xcd>, <&dmac1 0xce>; + dma-names = "tx", "rx", "tx", "rx"; + max-frequency = <195000000>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; + resets = <&cpg 314>; + }; + + sdhi1: sd@ee120000 { + compatible = "renesas,sdhi-r8a7790", "renesas,rcar-gen2-sdhi"; + reg = <0 0xee120000 0 0x328>; + interrupts = ; + clocks = <&cpg CPG_MOD 313>; + dmas = <&dmac0 0xc9>, <&dmac0 0xca>, + <&dmac1 0xc9>, <&dmac1 0xca>; + dma-names = "tx", "rx", "tx", "rx"; + max-frequency = <195000000>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; + resets = <&cpg 313>; + }; + + sdhi2: sd@ee140000 { + compatible = "renesas,sdhi-r8a7790", "renesas,rcar-gen2-sdhi"; + reg = <0 0xee140000 0 0x100>; + interrupts = ; + clocks = <&cpg CPG_MOD 312>; + dmas = <&dmac0 0xc1>, <&dmac0 0xc2>, + <&dmac1 0xc1>, <&dmac1 0xc2>; + dma-names = "tx", "rx", "tx", "rx"; + max-frequency = <97500000>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; + resets = <&cpg 312>; + }; + + sdhi3: sd@ee160000 { + compatible = "renesas,sdhi-r8a7790", "renesas,rcar-gen2-sdhi"; + reg = <0 0xee160000 0 0x100>; + interrupts = ; + clocks = <&cpg CPG_MOD 311>; + dmas = <&dmac0 0xd3>, <&dmac0 0xd4>, + <&dmac1 0xd3>, <&dmac1 0xd4>; + dma-names = "tx", "rx", "tx", "rx"; + max-frequency = <97500000>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; + resets = <&cpg 311>; + }; diff --git a/Documentation/devicetree/bindings/mmc/tmio_mmc.txt b/Documentation/devicetree/bindings/mmc/tmio_mmc.txt deleted file mode 100644 index 2b4f17ca9087..000000000000 --- a/Documentation/devicetree/bindings/mmc/tmio_mmc.txt +++ /dev/null @@ -1,120 +0,0 @@ -* Toshiba Mobile IO SD/MMC controller - -The tmio-mmc driver doesn't probe its devices actively, instead its binding to -devices is managed by either MFD drivers or by the sh_mobile_sdhi platform -driver. Those drivers supply the tmio-mmc driver with platform data, that either -describe hardware capabilities, known to them, or are obtained by them from -their own platform data or from their DT information. In the latter case all -compulsory and any optional properties, common to all SD/MMC drivers, as -described in mmc.txt, can be used. Additionally the following tmio_mmc-specific -optional bindings can be used. - -Required properties: -- compatible: should contain one or more of the following: - "renesas,sdhi-sh73a0" - SDHI IP on SH73A0 SoC - "renesas,sdhi-r7s72100" - SDHI IP on R7S72100 SoC - "renesas,sdhi-r7s9210" - SDHI IP on R7S9210 SoC - "renesas,sdhi-r8a73a4" - SDHI IP on R8A73A4 SoC - "renesas,sdhi-r8a7740" - SDHI IP on R8A7740 SoC - "renesas,sdhi-r8a7743" - SDHI IP on R8A7743 SoC - "renesas,sdhi-r8a7744" - SDHI IP on R8A7744 SoC - "renesas,sdhi-r8a7745" - SDHI IP on R8A7745 SoC - "renesas,sdhi-r8a774a1" - SDHI IP on R8A774A1 SoC - "renesas,sdhi-r8a774c0" - SDHI IP on R8A774C0 SoC - "renesas,sdhi-r8a77470" - SDHI IP on R8A77470 SoC - "renesas,sdhi-mmc-r8a77470" - SDHI/MMC IP on R8A77470 SoC - "renesas,sdhi-r8a7778" - SDHI IP on R8A7778 SoC - "renesas,sdhi-r8a7779" - SDHI IP on R8A7779 SoC - "renesas,sdhi-r8a7790" - SDHI IP on R8A7790 SoC - "renesas,sdhi-r8a7791" - SDHI IP on R8A7791 SoC - "renesas,sdhi-r8a7792" - SDHI IP on R8A7792 SoC - "renesas,sdhi-r8a7793" - SDHI IP on R8A7793 SoC - "renesas,sdhi-r8a7794" - SDHI IP on R8A7794 SoC - "renesas,sdhi-r8a7795" - SDHI IP on R8A7795 SoC - "renesas,sdhi-r8a7796" - SDHI IP on R8A7796 SoC - "renesas,sdhi-r8a77965" - SDHI IP on R8A77965 SoC - "renesas,sdhi-r8a77970" - SDHI IP on R8A77970 SoC - "renesas,sdhi-r8a77980" - SDHI IP on R8A77980 SoC - "renesas,sdhi-r8a77990" - SDHI IP on R8A77990 SoC - "renesas,sdhi-r8a77995" - SDHI IP on R8A77995 SoC - "renesas,sdhi-shmobile" - a generic sh-mobile SDHI controller - "renesas,rcar-gen1-sdhi" - a generic R-Car Gen1 SDHI controller - "renesas,rcar-gen2-sdhi" - a generic R-Car Gen2 and RZ/G1 SDHI - (not SDHI/MMC) controller - "renesas,rcar-gen3-sdhi" - a generic R-Car Gen3 or RZ/G2 - SDHI controller - - - When compatible with the generic version, nodes must list - the SoC-specific version corresponding to the platform - first followed by the generic version. - -- clocks: Most controllers only have 1 clock source per channel. However, on - some variations of this controller, the internal card detection - logic that exists in this controller is sectioned off to be run by a - separate second clock source to allow the main core clock to be turned - off to save power. - If 2 clocks are specified by the hardware, you must name them as - "core" and "cd". If the controller only has 1 clock, naming is not - required. - Devices which have more than 1 clock are listed below: - 2: R7S72100, R7S9210 - -Optional properties: -- pinctrl-names: should be "default", "state_uhs" -- pinctrl-0: should contain default/high speed pin ctrl -- pinctrl-1: should contain uhs mode pin ctrl - -Example: R8A7790 (R-Car H2) SDHI controller nodes - - sdhi0: sd@ee100000 { - compatible = "renesas,sdhi-r8a7790", "renesas,rcar-gen2-sdhi"; - reg = <0 0xee100000 0 0x328>; - interrupts = ; - clocks = <&cpg CPG_MOD 314>; - dmas = <&dmac0 0xcd>, <&dmac0 0xce>, - <&dmac1 0xcd>, <&dmac1 0xce>; - dma-names = "tx", "rx", "tx", "rx"; - max-frequency = <195000000>; - power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; - resets = <&cpg 314>; - }; - - sdhi1: sd@ee120000 { - compatible = "renesas,sdhi-r8a7790", "renesas,rcar-gen2-sdhi"; - reg = <0 0xee120000 0 0x328>; - interrupts = ; - clocks = <&cpg CPG_MOD 313>; - dmas = <&dmac0 0xc9>, <&dmac0 0xca>, - <&dmac1 0xc9>, <&dmac1 0xca>; - dma-names = "tx", "rx", "tx", "rx"; - max-frequency = <195000000>; - power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; - resets = <&cpg 313>; - }; - - sdhi2: sd@ee140000 { - compatible = "renesas,sdhi-r8a7790", "renesas,rcar-gen2-sdhi"; - reg = <0 0xee140000 0 0x100>; - interrupts = ; - clocks = <&cpg CPG_MOD 312>; - dmas = <&dmac0 0xc1>, <&dmac0 0xc2>, - <&dmac1 0xc1>, <&dmac1 0xc2>; - dma-names = "tx", "rx", "tx", "rx"; - max-frequency = <97500000>; - power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; - resets = <&cpg 312>; - }; - - sdhi3: sd@ee160000 { - compatible = "renesas,sdhi-r8a7790", "renesas,rcar-gen2-sdhi"; - reg = <0 0xee160000 0 0x100>; - interrupts = ; - clocks = <&cpg CPG_MOD 311>; - dmas = <&dmac0 0xd3>, <&dmac0 0xd4>, - <&dmac1 0xd3>, <&dmac1 0xd4>; - dma-names = "tx", "rx", "tx", "rx"; - max-frequency = <97500000>; - power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; - resets = <&cpg 311>; - }; -- cgit v1.2.3-59-g8ed1b From 7559d612dff0389aba5b49664e3bc94a150e45f2 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 25 Jun 2019 11:20:41 +0200 Subject: mmc: core: let the dma map ops handle bouncing Just like we do for all other block drivers. Especially as the limit imposed at the moment might be way to pessimistic for iommus. This also means we are not going to set a bounce limit for the queue, in case we have a dma mask. On most architectures it was never needed, the major hold out was x86-32 with PAE, but that has been fixed by now. Signed-off-by: Christoph Hellwig Signed-off-by: Ulf Hansson --- drivers/mmc/core/queue.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c index 92900a095796..4bf9cd881bd0 100644 --- a/drivers/mmc/core/queue.c +++ b/drivers/mmc/core/queue.c @@ -354,18 +354,15 @@ static const struct blk_mq_ops mmc_mq_ops = { static void mmc_setup_queue(struct mmc_queue *mq, struct mmc_card *card) { struct mmc_host *host = card->host; - u64 limit = BLK_BOUNCE_HIGH; unsigned block_size = 512; - if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask) - limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT; - blk_queue_flag_set(QUEUE_FLAG_NONROT, mq->queue); blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, mq->queue); if (mmc_can_erase(card)) mmc_queue_setup_discard(mq->queue, card); - blk_queue_bounce_limit(mq->queue, limit); + if (!mmc_dev(host)->dma_mask || !*mmc_dev(host)->dma_mask) + blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_HIGH); blk_queue_max_hw_sectors(mq->queue, min(host->max_blk_count, host->max_req_size / 512)); blk_queue_max_segments(mq->queue, host->max_segs); -- cgit v1.2.3-59-g8ed1b From 79a986721decf428ba539e6e2c941c987acce655 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 25 Jun 2019 11:20:42 +0200 Subject: dma-mapping: remove dma_max_pfn These days, the DMA mapping code must bounce buffers for any unsupported address. If the driver needs to optimize for natively supported ranges, then it should use dma_get_required_mask. Signed-off-by: Christoph Hellwig Acked-by: Marc Gonzalez Signed-off-by: Ulf Hansson --- arch/arm/include/asm/dma-mapping.h | 7 ------- include/linux/dma-mapping.h | 7 ------- 2 files changed, 14 deletions(-) diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index 03ba90ffc0f8..7e0486ad1318 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -89,13 +89,6 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr) } #endif -/* The ARM override for dma_max_pfn() */ -static inline unsigned long dma_max_pfn(struct device *dev) -{ - return dma_to_pfn(dev, *dev->dma_mask); -} -#define dma_max_pfn(dev) dma_max_pfn(dev) - /* do not use this function in a driver */ static inline bool is_device_dma_coherent(struct device *dev) { diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index 6309a721394b..8d13e28a8e07 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -729,13 +729,6 @@ static inline int dma_set_seg_boundary(struct device *dev, unsigned long mask) return -EIO; } -#ifndef dma_max_pfn -static inline unsigned long dma_max_pfn(struct device *dev) -{ - return (*dev->dma_mask >> PAGE_SHIFT) + dev->dma_pfn_offset; -} -#endif - static inline int dma_get_cache_alignment(void) { #ifdef ARCH_DMA_MINALIGN -- cgit v1.2.3-59-g8ed1b From 8751c8bd8b91abb0887ab971651a1ac72d3b9398 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 28 Jun 2019 12:07:51 +0800 Subject: mmc: sdhci_am654: Make some symbols static Fix sparse warnings: drivers/mmc/host/sdhci_am654.c:192:6: warning: symbol 'sdhci_j721e_4bit_set_clock' was not declared. Should it be static? drivers/mmc/host/sdhci_am654.c:261:18: warning: symbol 'sdhci_j721e_8bit_ops' was not declared. Should it be static? drivers/mmc/host/sdhci_am654.c:284:18: warning: symbol 'sdhci_j721e_4bit_ops' was not declared. Should it be static? Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci_am654.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index 3b3948144591..bb90757ecace 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -189,7 +189,8 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock) } } -void sdhci_j721e_4bit_set_clock(struct sdhci_host *host, unsigned int clock) +static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host, + unsigned int clock) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host); @@ -258,7 +259,7 @@ static const struct sdhci_am654_driver_data sdhci_am654_drvdata = { .flags = IOMUX_PRESENT | FREQSEL_2_BIT | STRBSEL_4_BIT | DLL_PRESENT, }; -struct sdhci_ops sdhci_j721e_8bit_ops = { +static struct sdhci_ops sdhci_j721e_8bit_ops = { .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, @@ -281,7 +282,7 @@ static const struct sdhci_am654_driver_data sdhci_j721e_8bit_drvdata = { .flags = DLL_PRESENT, }; -struct sdhci_ops sdhci_j721e_4bit_ops = { +static struct sdhci_ops sdhci_j721e_4bit_ops = { .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, -- cgit v1.2.3-59-g8ed1b From 5e6b6651d22de109ebf48ca00d0373bc2c0cc080 Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Mon, 1 Jul 2019 17:01:25 +0200 Subject: mmc: sdhci-msm: fix mutex while in spinlock mutexes can sleep and therefore should not be taken while holding a spinlock. move clk_get_rate (can sleep) outside the spinlock protected region. Fixes: 83736352e0ca ("mmc: sdhci-msm: Update DLL reset sequence") Cc: stable@vger.kernel.org Signed-off-by: Jorge Ramirez-Ortiz Reviewed-by: Bjorn Andersson Reviewed-by: Vinod Koul Acked-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci-msm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 5fc76a1993d0..9cf14b359c14 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -575,11 +575,14 @@ static int msm_init_cm_dll(struct sdhci_host *host) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); int wait_cnt = 50; - unsigned long flags; + unsigned long flags, xo_clk = 0; u32 config; const struct sdhci_msm_offset *msm_offset = msm_host->offset; + if (msm_host->use_14lpp_dll_reset && !IS_ERR_OR_NULL(msm_host->xo_clk)) + xo_clk = clk_get_rate(msm_host->xo_clk); + spin_lock_irqsave(&host->lock, flags); /* @@ -627,10 +630,10 @@ static int msm_init_cm_dll(struct sdhci_host *host) config &= CORE_FLL_CYCLE_CNT; if (config) mclk_freq = DIV_ROUND_CLOSEST_ULL((host->clock * 8), - clk_get_rate(msm_host->xo_clk)); + xo_clk); else mclk_freq = DIV_ROUND_CLOSEST_ULL((host->clock * 4), - clk_get_rate(msm_host->xo_clk)); + xo_clk); config = readl_relaxed(host->ioaddr + msm_offset->core_dll_config_2); -- cgit v1.2.3-59-g8ed1b From 42248a918d7c18a535b08f05badb988b140298f6 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 1 Jul 2019 18:52:46 +0100 Subject: mmc: alcor: remove a redundant greater or equal to zero comparison A greater or equal comparison on the unsigned int variable tmp_diff is always true as unsigned ints are never negative. Hence the comparison is redundant and can be removed. Addresses-Coverity: ("Unsigned compared against 0") Signed-off-by: Colin Ian King Signed-off-by: Ulf Hansson --- drivers/mmc/host/alcor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/alcor.c b/drivers/mmc/host/alcor.c index e481535cba2b..1aee485d56d4 100644 --- a/drivers/mmc/host/alcor.c +++ b/drivers/mmc/host/alcor.c @@ -672,7 +672,7 @@ static void alcor_set_clock(struct alcor_sdmmc_host *host, unsigned int clock) tmp_clock = DIV_ROUND_UP(cfg->clk_src_freq, tmp_div); tmp_diff = abs(clock - tmp_clock); - if (tmp_diff >= 0 && tmp_diff < diff) { + if (tmp_diff < diff) { diff = tmp_diff; clk_src = cfg->clk_src_reg; clk_div = tmp_div; -- cgit v1.2.3-59-g8ed1b From 59592cc1f5937ced72e11e681c3e358a0375f7ae Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Tue, 2 Jul 2019 21:36:31 +0800 Subject: mmc: sdhci_am654: Add dependency on MMC_SDHCI_AM654 Fix build error: drivers/mmc/host/sdhci_am654.o: In function `sdhci_am654_probe': drivers/mmc/host/sdhci_am654.c:464: undefined reference to `__devm_regmap_init_mmio_clk' drivers/mmc/host/sdhci_am654.o:(.debug_addr+0x3f8): undefined reference to `__devm_regmap_init_mmio_clk' Reported-by: Hulk Robot Fixes: aff88ff23512 ("mmc: sdhci_am654: Add Initial Support for AM654 SDHCI driver") Signed-off-by: YueHaibing 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 931770f17087..14d89a108edd 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -996,7 +996,7 @@ config MMC_SDHCI_OMAP config MMC_SDHCI_AM654 tristate "Support for the SDHCI Controller in TI's AM654 SOCs" - depends on MMC_SDHCI_PLTFM && OF + depends on MMC_SDHCI_PLTFM && OF && REGMAP_MMIO select MMC_SDHCI_IO_ACCESSORS help This selects the Secure Digital Host Controller Interface (SDHCI) -- cgit v1.2.3-59-g8ed1b