diff options
Diffstat (limited to 'drivers/mmc/host')
75 files changed, 804 insertions, 553 deletions
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 159a3e9490ae..554e67103c1a 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -526,11 +526,12 @@ config MMC_ALCOR of Alcor Micro PCI-E card reader config MMC_AU1X - tristate "Alchemy AU1XX0 MMC Card Interface support" + bool "Alchemy AU1XX0 MMC Card Interface support" depends on MIPS_ALCHEMY + depends on MMC=y help This selects the AMD Alchemy(R) Multimedia card interface. - If you have a Alchemy platform with a MMC slot, say Y or M here. + If you have a Alchemy platform with a MMC slot, say Y here. If unsure, say N. diff --git a/drivers/mmc/host/alcor.c b/drivers/mmc/host/alcor.c index d01df01d4b4d..42aa43740ba8 100644 --- a/drivers/mmc/host/alcor.c +++ b/drivers/mmc/host/alcor.c @@ -1125,7 +1125,7 @@ free_host: return ret; } -static int alcor_pci_sdmmc_drv_remove(struct platform_device *pdev) +static void alcor_pci_sdmmc_drv_remove(struct platform_device *pdev) { struct alcor_sdmmc_host *host = dev_get_drvdata(&pdev->dev); struct mmc_host *mmc = mmc_from_priv(host); @@ -1136,8 +1136,6 @@ static int alcor_pci_sdmmc_drv_remove(struct platform_device *pdev) alcor_hw_uninit(host); mmc_remove_host(mmc); mmc_free_host(mmc); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1177,7 +1175,7 @@ MODULE_DEVICE_TABLE(platform, alcor_pci_sdmmc_ids); static struct platform_driver alcor_pci_sdmmc_driver = { .probe = alcor_pci_sdmmc_drv_probe, - .remove = alcor_pci_sdmmc_drv_remove, + .remove_new = alcor_pci_sdmmc_drv_remove, .id_table = alcor_pci_sdmmc_ids, .driver = { .name = DRV_NAME_ALCOR_PCI_SDMMC, diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index dd18440a90c5..535783c43105 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -11,15 +11,14 @@ #include <linux/dmaengine.h> #include <linux/dma-mapping.h> #include <linux/err.h> -#include <linux/gpio.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/ioport.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_gpio.h> +#include <linux/irq.h> +#include <linux/gpio/consumer.h> #include <linux/platform_device.h> #include <linux/scatterlist.h> #include <linux/seq_file.h> @@ -30,7 +29,6 @@ #include <linux/mmc/host.h> #include <linux/mmc/sdio.h> -#include <linux/atmel-mci.h> #include <linux/atmel_pdc.h> #include <linux/pm.h> #include <linux/pm_runtime.h> @@ -40,6 +38,8 @@ #include <asm/io.h> #include <asm/unaligned.h> +#define ATMCI_MAX_NR_SLOTS 2 + /* * Superset of MCI IP registers integrated in Atmel AT91 Processor * Registers and bitfields marked with [2] are only available in MCI2 @@ -201,6 +201,40 @@ enum atmci_pdc_buf { PDC_SECOND_BUF, }; +/** + * struct mci_slot_pdata - board-specific per-slot configuration + * @bus_width: Number of data lines wired up the slot + * @detect_pin: GPIO pin wired to the card detect switch + * @wp_pin: GPIO pin wired to the write protect sensor + * @non_removable: The slot is not removable, only detect once + * + * If a given slot is not present on the board, @bus_width should be + * set to 0. The other fields are ignored in this case. + * + * Any pins that aren't available should be set to a negative value. + * + * Note that support for multiple slots is experimental -- some cards + * might get upset if we don't get the clock management exactly right. + * But in most cases, it should work just fine. + */ +struct mci_slot_pdata { + unsigned int bus_width; + struct gpio_desc *detect_pin; + struct gpio_desc *wp_pin; + bool non_removable; +}; + +/** + * struct mci_platform_data - board-specific MMC/SDcard configuration + * @dma_slave: DMA slave interface to use in data transfers. + * @slot: Per-slot configuration data. + */ +struct mci_platform_data { + void *dma_slave; + dma_filter_fn dma_filter; + struct mci_slot_pdata slot[ATMCI_MAX_NR_SLOTS]; +}; + struct atmel_mci_caps { bool has_dma_conf_reg; bool has_pdc; @@ -369,7 +403,6 @@ struct atmel_mci { * available. * @wp_pin: GPIO pin used for card write protect sending, or negative * if not available. - * @detect_is_active_high: The state of the detect pin when it is active. * @detect_timer: Timer used for debouncing @detect_pin interrupts. */ struct atmel_mci_slot { @@ -388,9 +421,8 @@ struct atmel_mci_slot { #define ATMCI_CARD_NEED_INIT 1 #define ATMCI_SHUTDOWN 2 - int detect_pin; - int wp_pin; - bool detect_is_active_high; + struct gpio_desc *detect_pin; + struct gpio_desc *wp_pin; struct timer_list detect_timer; }; @@ -608,6 +640,7 @@ atmci_of_init(struct platform_device *pdev) struct device_node *cnp; struct mci_platform_data *pdata; u32 slot_id; + int err; if (!np) { dev_err(&pdev->dev, "device node not found\n"); @@ -637,16 +670,27 @@ atmci_of_init(struct platform_device *pdev) pdata->slot[slot_id].bus_width = 1; pdata->slot[slot_id].detect_pin = - of_get_named_gpio(cnp, "cd-gpios", 0); - - pdata->slot[slot_id].detect_is_active_high = - of_property_read_bool(cnp, "cd-inverted"); + devm_fwnode_gpiod_get(&pdev->dev, of_fwnode_handle(cnp), + "cd", GPIOD_IN, "cd-gpios"); + err = PTR_ERR_OR_ZERO(pdata->slot[slot_id].detect_pin); + if (err) { + if (err != -ENOENT) + return ERR_PTR(err); + pdata->slot[slot_id].detect_pin = NULL; + } pdata->slot[slot_id].non_removable = of_property_read_bool(cnp, "non-removable"); pdata->slot[slot_id].wp_pin = - of_get_named_gpio(cnp, "wp-gpios", 0); + devm_fwnode_gpiod_get(&pdev->dev, of_fwnode_handle(cnp), + "wp", GPIOD_IN, "wp-gpios"); + err = PTR_ERR_OR_ZERO(pdata->slot[slot_id].wp_pin); + if (err) { + if (err != -ENOENT) + return ERR_PTR(err); + pdata->slot[slot_id].wp_pin = NULL; + } } return pdata; @@ -1509,8 +1553,8 @@ static int atmci_get_ro(struct mmc_host *mmc) int read_only = -ENOSYS; struct atmel_mci_slot *slot = mmc_priv(mmc); - if (gpio_is_valid(slot->wp_pin)) { - read_only = gpio_get_value(slot->wp_pin); + if (slot->wp_pin) { + read_only = gpiod_get_value(slot->wp_pin); dev_dbg(&mmc->class_dev, "card is %s\n", read_only ? "read-only" : "read-write"); } @@ -1523,9 +1567,8 @@ static int atmci_get_cd(struct mmc_host *mmc) int present = -ENOSYS; struct atmel_mci_slot *slot = mmc_priv(mmc); - if (gpio_is_valid(slot->detect_pin)) { - present = !(gpio_get_value(slot->detect_pin) ^ - slot->detect_is_active_high); + if (slot->detect_pin) { + present = gpiod_get_value_cansleep(slot->detect_pin); dev_dbg(&mmc->class_dev, "card is %spresent\n", present ? "" : "not "); } @@ -1637,9 +1680,8 @@ static void atmci_detect_change(struct timer_list *t) if (test_bit(ATMCI_SHUTDOWN, &slot->flags)) return; - enable_irq(gpio_to_irq(slot->detect_pin)); - present = !(gpio_get_value(slot->detect_pin) ^ - slot->detect_is_active_high); + enable_irq(gpiod_to_irq(slot->detect_pin)); + present = gpiod_get_value_cansleep(slot->detect_pin); present_old = test_bit(ATMCI_CARD_PRESENT, &slot->flags); dev_vdbg(&slot->mmc->class_dev, "detect change: %d (was %d)\n", @@ -2230,16 +2272,15 @@ static int atmci_init_slot(struct atmel_mci *host, slot->host = host; slot->detect_pin = slot_data->detect_pin; slot->wp_pin = slot_data->wp_pin; - slot->detect_is_active_high = slot_data->detect_is_active_high; slot->sdc_reg = sdc_reg; slot->sdio_irq = sdio_irq; dev_dbg(&mmc->class_dev, "slot[%u]: bus_width=%u, detect_pin=%d, " "detect_is_active_high=%s, wp_pin=%d\n", - id, slot_data->bus_width, slot_data->detect_pin, - slot_data->detect_is_active_high ? "true" : "false", - slot_data->wp_pin); + id, slot_data->bus_width, desc_to_gpio(slot_data->detect_pin), + !gpiod_is_active_low(slot_data->detect_pin) ? "true" : "false", + desc_to_gpio(slot_data->wp_pin)); mmc->ops = &atmci_ops; mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512); @@ -2275,31 +2316,22 @@ static int atmci_init_slot(struct atmel_mci *host, /* Assume card is present initially */ set_bit(ATMCI_CARD_PRESENT, &slot->flags); - if (gpio_is_valid(slot->detect_pin)) { - if (devm_gpio_request(&host->pdev->dev, slot->detect_pin, - "mmc_detect")) { - dev_dbg(&mmc->class_dev, "no detect pin available\n"); - slot->detect_pin = -EBUSY; - } else if (gpio_get_value(slot->detect_pin) ^ - slot->detect_is_active_high) { + if (slot->detect_pin) { + if (!gpiod_get_value_cansleep(slot->detect_pin)) clear_bit(ATMCI_CARD_PRESENT, &slot->flags); - } + } else { + dev_dbg(&mmc->class_dev, "no detect pin available\n"); } - if (!gpio_is_valid(slot->detect_pin)) { + if (!slot->detect_pin) { if (slot_data->non_removable) mmc->caps |= MMC_CAP_NONREMOVABLE; else mmc->caps |= MMC_CAP_NEEDS_POLL; } - if (gpio_is_valid(slot->wp_pin)) { - if (devm_gpio_request(&host->pdev->dev, slot->wp_pin, - "mmc_wp")) { - dev_dbg(&mmc->class_dev, "no WP pin available\n"); - slot->wp_pin = -EBUSY; - } - } + if (!slot->wp_pin) + dev_dbg(&mmc->class_dev, "no WP pin available\n"); host->slot[id] = slot; mmc_regulator_get_supply(mmc); @@ -2309,18 +2341,18 @@ static int atmci_init_slot(struct atmel_mci *host, return ret; } - if (gpio_is_valid(slot->detect_pin)) { + if (slot->detect_pin) { timer_setup(&slot->detect_timer, atmci_detect_change, 0); - ret = request_irq(gpio_to_irq(slot->detect_pin), - atmci_detect_interrupt, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - "mmc-detect", slot); + ret = request_irq(gpiod_to_irq(slot->detect_pin), + atmci_detect_interrupt, + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, + "mmc-detect", slot); if (ret) { dev_dbg(&mmc->class_dev, "could not request IRQ %d for detect pin\n", - gpio_to_irq(slot->detect_pin)); - slot->detect_pin = -EBUSY; + gpiod_to_irq(slot->detect_pin)); + slot->detect_pin = NULL; } } @@ -2339,10 +2371,8 @@ static void atmci_cleanup_slot(struct atmel_mci_slot *slot, mmc_remove_host(slot->mmc); - if (gpio_is_valid(slot->detect_pin)) { - int pin = slot->detect_pin; - - free_irq(gpio_to_irq(pin), slot); + if (slot->detect_pin) { + free_irq(gpiod_to_irq(slot->detect_pin), slot); del_timer_sync(&slot->detect_timer); } @@ -2600,7 +2630,7 @@ err_dma_probe_defer: return ret; } -static int atmci_remove(struct platform_device *pdev) +static void atmci_remove(struct platform_device *pdev) { struct atmel_mci *host = platform_get_drvdata(pdev); unsigned int i; @@ -2630,8 +2660,6 @@ static int atmci_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); - - return 0; } #ifdef CONFIG_PM @@ -2664,7 +2692,7 @@ static const struct dev_pm_ops atmci_dev_pm_ops = { static struct platform_driver atmci_driver = { .probe = atmci_probe, - .remove = atmci_remove, + .remove_new = atmci_remove, .driver = { .name = "atmel_mci", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index 82dd0ae40305..b5a5c6a2fe8b 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c @@ -1114,7 +1114,7 @@ out0: return ret; } -static int au1xmmc_remove(struct platform_device *pdev) +static void au1xmmc_remove(struct platform_device *pdev) { struct au1xmmc_host *host = platform_get_drvdata(pdev); @@ -1153,7 +1153,6 @@ static int au1xmmc_remove(struct platform_device *pdev) mmc_free_host(host->mmc); } - return 0; } #ifdef CONFIG_PM @@ -1185,7 +1184,7 @@ static int au1xmmc_resume(struct platform_device *pdev) static struct platform_driver au1xmmc_driver = { .probe = au1xmmc_probe, - .remove = au1xmmc_remove, + .remove_new = au1xmmc_remove, .suspend = au1xmmc_suspend, .resume = au1xmmc_resume, .driver = { diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c index eea208856ce0..35d8fdea668b 100644 --- a/drivers/mmc/host/bcm2835.c +++ b/drivers/mmc/host/bcm2835.c @@ -1431,7 +1431,7 @@ err: return ret; } -static int bcm2835_remove(struct platform_device *pdev) +static void bcm2835_remove(struct platform_device *pdev) { struct bcm2835_host *host = platform_get_drvdata(pdev); struct mmc_host *mmc = mmc_from_priv(host); @@ -1449,8 +1449,6 @@ static int bcm2835_remove(struct platform_device *pdev) dma_release_channel(host->dma_chan_rxtx); mmc_free_host(mmc); - - return 0; } static const struct of_device_id bcm2835_match[] = { @@ -1461,7 +1459,7 @@ MODULE_DEVICE_TABLE(of, bcm2835_match); static struct platform_driver bcm2835_driver = { .probe = bcm2835_probe, - .remove = bcm2835_remove, + .remove_new = bcm2835_remove, .driver = { .name = "sdhost-bcm2835", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/cavium-octeon.c b/drivers/mmc/host/cavium-octeon.c index 12dca91a8ef6..060ec4f4800f 100644 --- a/drivers/mmc/host/cavium-octeon.c +++ b/drivers/mmc/host/cavium-octeon.c @@ -13,7 +13,9 @@ #include <linux/mmc/mmc.h> #include <linux/mmc/slot-gpio.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/of_platform.h> +#include <linux/platform_device.h> #include <asm/octeon/octeon.h> #include "cavium.h" @@ -294,7 +296,7 @@ error: return ret; } -static int octeon_mmc_remove(struct platform_device *pdev) +static void octeon_mmc_remove(struct platform_device *pdev) { struct cvm_mmc_host *host = platform_get_drvdata(pdev); u64 dma_cfg; @@ -309,7 +311,6 @@ static int octeon_mmc_remove(struct platform_device *pdev) writeq(dma_cfg, host->dma_base + MIO_EMM_DMA_CFG(host)); octeon_mmc_set_shared_power(host, 0); - return 0; } static const struct of_device_id octeon_mmc_match[] = { @@ -325,7 +326,7 @@ MODULE_DEVICE_TABLE(of, octeon_mmc_match); static struct platform_driver octeon_mmc_driver = { .probe = octeon_mmc_probe, - .remove = octeon_mmc_remove, + .remove_new = octeon_mmc_remove, .driver = { .name = KBUILD_MODNAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/cavium-thunderx.c b/drivers/mmc/host/cavium-thunderx.c index 202b1d6da678..2e2ff984f0b3 100644 --- a/drivers/mmc/host/cavium-thunderx.c +++ b/drivers/mmc/host/cavium-thunderx.c @@ -14,6 +14,7 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/pci.h> #include "cavium.h" diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c index 6d623b2681c3..0aec33b88bef 100644 --- a/drivers/mmc/host/cb710-mmc.c +++ b/drivers/mmc/host/cb710-mmc.c @@ -745,7 +745,7 @@ err_free_mmc: return err; } -static int cb710_mmc_exit(struct platform_device *pdev) +static void cb710_mmc_exit(struct platform_device *pdev) { struct cb710_slot *slot = cb710_pdev_to_slot(pdev); struct mmc_host *mmc = cb710_slot_to_mmc(slot); @@ -766,13 +766,12 @@ static int cb710_mmc_exit(struct platform_device *pdev) tasklet_kill(&reader->finish_req_tasklet); mmc_free_host(mmc); - return 0; } static struct platform_driver cb710_mmc_driver = { .driver.name = "cb710-mmc", .probe = cb710_mmc_init, - .remove = cb710_mmc_exit, + .remove_new = cb710_mmc_exit, #ifdef CONFIG_PM .suspend = cb710_mmc_suspend, .resume = cb710_mmc_resume, diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index 7138dfa065bf..ee3b1a4e0848 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c @@ -21,7 +21,6 @@ #include <linux/dma-mapping.h> #include <linux/mmc/mmc.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/mmc/slot-gpio.h> #include <linux/interrupt.h> @@ -1257,7 +1256,7 @@ static int davinci_mmcsd_probe(struct platform_device *pdev) host->use_dma = use_dma; host->mmc_irq = irq; - host->sdio_irq = platform_get_irq(pdev, 1); + host->sdio_irq = platform_get_irq_optional(pdev, 1); if (host->use_dma) { ret = davinci_acquire_dma_channels(host); @@ -1345,7 +1344,7 @@ ioremap_fail: return ret; } -static int __exit davinci_mmcsd_remove(struct platform_device *pdev) +static void __exit davinci_mmcsd_remove(struct platform_device *pdev) { struct mmc_davinci_host *host = platform_get_drvdata(pdev); @@ -1354,8 +1353,6 @@ static int __exit davinci_mmcsd_remove(struct platform_device *pdev) davinci_release_dma_channels(host); clk_disable_unprepare(host->clk); mmc_free_host(host->mmc); - - return 0; } #ifdef CONFIG_PM @@ -1402,7 +1399,7 @@ static struct platform_driver davinci_mmcsd_driver = { .of_match_table = davinci_mmc_dt_ids, }, .probe = davinci_mmcsd_probe, - .remove = __exit_p(davinci_mmcsd_remove), + .remove_new = __exit_p(davinci_mmcsd_remove), .id_table = davinci_mmc_devtype, }; diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 9f20ac524c8b..698408e8bad0 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -664,15 +664,13 @@ static int dw_mci_exynos_probe(struct platform_device *pdev) return 0; } -static int dw_mci_exynos_remove(struct platform_device *pdev) +static void dw_mci_exynos_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); dw_mci_pltfm_remove(pdev); - - return 0; } static const struct dev_pm_ops dw_mci_exynos_pmops = { @@ -685,7 +683,7 @@ static const struct dev_pm_ops dw_mci_exynos_pmops = { static struct platform_driver dw_mci_exynos_pltfm_driver = { .probe = dw_mci_exynos_probe, - .remove = dw_mci_exynos_remove, + .remove_new = dw_mci_exynos_remove, .driver = { .name = "dwmmc_exynos", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/dw_mmc-hi3798cv200.c b/drivers/mmc/host/dw_mmc-hi3798cv200.c index 6f22fe054087..e9470c50a348 100644 --- a/drivers/mmc/host/dw_mmc-hi3798cv200.c +++ b/drivers/mmc/host/dw_mmc-hi3798cv200.c @@ -171,7 +171,7 @@ static int dw_mci_hi3798cv200_probe(struct platform_device *pdev) return dw_mci_pltfm_register(pdev, &hi3798cv200_data); } -static int dw_mci_hi3798cv200_remove(struct platform_device *pdev) +static void dw_mci_hi3798cv200_remove(struct platform_device *pdev) { struct dw_mci *host = platform_get_drvdata(pdev); struct hi3798cv200_priv *priv = host->priv; @@ -180,8 +180,6 @@ static int dw_mci_hi3798cv200_remove(struct platform_device *pdev) clk_disable_unprepare(priv->sample_clk); dw_mci_pltfm_remove(pdev); - - return 0; } static const struct of_device_id dw_mci_hi3798cv200_match[] = { @@ -192,7 +190,7 @@ static const struct of_device_id dw_mci_hi3798cv200_match[] = { MODULE_DEVICE_TABLE(of, dw_mci_hi3798cv200_match); static struct platform_driver dw_mci_hi3798cv200_driver = { .probe = dw_mci_hi3798cv200_probe, - .remove = dw_mci_hi3798cv200_remove, + .remove_new = dw_mci_hi3798cv200_remove, .driver = { .name = "dwmmc_hi3798cv200", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c index 2a99f15f527f..b07190ba4b7a 100644 --- a/drivers/mmc/host/dw_mmc-rockchip.c +++ b/drivers/mmc/host/dw_mmc-rockchip.c @@ -371,15 +371,13 @@ static int dw_mci_rockchip_probe(struct platform_device *pdev) return 0; } -static int dw_mci_rockchip_remove(struct platform_device *pdev) +static void dw_mci_rockchip_remove(struct platform_device *pdev) { pm_runtime_get_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); dw_mci_pltfm_remove(pdev); - - return 0; } static const struct dev_pm_ops dw_mci_rockchip_dev_pm_ops = { @@ -392,7 +390,7 @@ static const struct dev_pm_ops dw_mci_rockchip_dev_pm_ops = { static struct platform_driver dw_mci_rockchip_pltfm_driver = { .probe = dw_mci_rockchip_probe, - .remove = dw_mci_rockchip_remove, + .remove_new = dw_mci_rockchip_remove, .driver = { .name = "dwmmc_rockchip", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index 1846a05210e3..f379ce5b582d 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -1163,7 +1163,7 @@ err_free_host: return ret; } -static int jz4740_mmc_remove(struct platform_device *pdev) +static void jz4740_mmc_remove(struct platform_device *pdev) { struct jz4740_mmc_host *host = platform_get_drvdata(pdev); @@ -1179,8 +1179,6 @@ static int jz4740_mmc_remove(struct platform_device *pdev) jz4740_mmc_release_dma_channels(host); mmc_free_host(host->mmc); - - return 0; } static int jz4740_mmc_suspend(struct device *dev) @@ -1198,7 +1196,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(jz4740_mmc_pm_ops, jz4740_mmc_suspend, static struct platform_driver jz4740_mmc_driver = { .probe = jz4740_mmc_probe, - .remove = jz4740_mmc_remove, + .remove_new = jz4740_mmc_remove, .driver = { .name = "jz4740-mmc", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/litex_mmc.c b/drivers/mmc/host/litex_mmc.c index 9af6b0902efe..4ec8072dc60b 100644 --- a/drivers/mmc/host/litex_mmc.c +++ b/drivers/mmc/host/litex_mmc.c @@ -629,12 +629,11 @@ static int litex_mmc_probe(struct platform_device *pdev) return 0; } -static int litex_mmc_remove(struct platform_device *pdev) +static void litex_mmc_remove(struct platform_device *pdev) { struct litex_mmc_host *host = platform_get_drvdata(pdev); mmc_remove_host(host->mmc); - return 0; } static const struct of_device_id litex_match[] = { @@ -645,7 +644,7 @@ MODULE_DEVICE_TABLE(of, litex_match); static struct platform_driver litex_mmc_driver = { .probe = litex_mmc_probe, - .remove = litex_mmc_remove, + .remove_new = litex_mmc_remove, .driver = { .name = "litex-mmc", .of_match_table = litex_match, diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index ee9a25b900ae..9837dab096e6 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -11,7 +11,7 @@ #include <linux/delay.h> #include <linux/device.h> #include <linux/iopoll.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/ioport.h> #include <linux/dma-mapping.h> @@ -948,9 +948,6 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) return IRQ_NONE; } - if (WARN_ON(!host)) - return IRQ_NONE; - /* ack all raised interrupts */ writel(status, host->regs + SD_EMMC_STATUS); @@ -1297,7 +1294,7 @@ err_init_clk: return ret; } -static int meson_mmc_remove(struct platform_device *pdev) +static void meson_mmc_remove(struct platform_device *pdev) { struct meson_host *host = dev_get_drvdata(&pdev->dev); @@ -1308,8 +1305,6 @@ static int meson_mmc_remove(struct platform_device *pdev) free_irq(host->irq, host); clk_disable_unprepare(host->mmc_clk); - - return 0; } static const struct meson_mmc_data meson_gx_data = { @@ -1340,7 +1335,7 @@ MODULE_DEVICE_TABLE(of, meson_mmc_of_match); static struct platform_driver meson_mmc_driver = { .probe = meson_mmc_probe, - .remove = meson_mmc_remove, + .remove_new = meson_mmc_remove, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/meson-mx-sdhc-mmc.c b/drivers/mmc/host/meson-mx-sdhc-mmc.c index 97168cdfa8e9..528ec8166e7c 100644 --- a/drivers/mmc/host/meson-mx-sdhc-mmc.c +++ b/drivers/mmc/host/meson-mx-sdhc-mmc.c @@ -880,7 +880,7 @@ err_disable_pclk: return ret; } -static int meson_mx_sdhc_remove(struct platform_device *pdev) +static void meson_mx_sdhc_remove(struct platform_device *pdev) { struct meson_mx_sdhc_host *host = platform_get_drvdata(pdev); @@ -889,8 +889,6 @@ static int meson_mx_sdhc_remove(struct platform_device *pdev) meson_mx_sdhc_disable_clks(host->mmc); clk_disable_unprepare(host->pclk); - - return 0; } static const struct meson_mx_sdhc_data meson_mx_sdhc_data_meson8 = { @@ -925,7 +923,7 @@ MODULE_DEVICE_TABLE(of, meson_mx_sdhc_of_match); static struct platform_driver meson_mx_sdhc_driver = { .probe = meson_mx_sdhc_probe, - .remove = meson_mx_sdhc_remove, + .remove_new = meson_mx_sdhc_remove, .driver = { .name = "meson-mx-sdhc", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/meson-mx-sdio.c b/drivers/mmc/host/meson-mx-sdio.c index 3a19a05ef55a..a11577f2ee69 100644 --- a/drivers/mmc/host/meson-mx-sdio.c +++ b/drivers/mmc/host/meson-mx-sdio.c @@ -728,7 +728,7 @@ error_unregister_slot_pdev: return ret; } -static int meson_mx_mmc_remove(struct platform_device *pdev) +static void meson_mx_mmc_remove(struct platform_device *pdev) { struct meson_mx_mmc_host *host = platform_get_drvdata(pdev); struct device *slot_dev = mmc_dev(host->mmc); @@ -743,8 +743,6 @@ static int meson_mx_mmc_remove(struct platform_device *pdev) clk_disable_unprepare(host->core_clk); mmc_free_host(host->mmc); - - return 0; } static const struct of_device_id meson_mx_mmc_of_match[] = { @@ -756,7 +754,7 @@ MODULE_DEVICE_TABLE(of, meson_mx_mmc_of_match); static struct platform_driver meson_mx_mmc_driver = { .probe = meson_mx_mmc_probe, - .remove = meson_mx_mmc_remove, + .remove_new = meson_mx_mmc_remove, .driver = { .name = "meson-mx-sdio", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 769b34afa835..dda756a56379 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -764,7 +764,8 @@ static bool ux500_busy_complete(struct mmci_host *host, struct mmc_command *cmd, } retries--; } - dev_dbg(mmc_dev(host->mmc), "no busy signalling in time\n"); + dev_dbg(mmc_dev(host->mmc), + "no busy signalling in time CMD%02x\n", cmd->opcode); ux500_busy_clear_mask_done(host); break; @@ -786,7 +787,8 @@ static bool ux500_busy_complete(struct mmci_host *host, struct mmc_command *cmd, host->busy_state = MMCI_BUSY_WAITING_FOR_END_IRQ; } else { dev_dbg(mmc_dev(host->mmc), - "lost busy status when waiting for busy start IRQ\n"); + "lost busy status when waiting for busy start IRQ CMD%02x\n", + cmd->opcode); cancel_delayed_work(&host->ux500_busy_timeout_work); ux500_busy_clear_mask_done(host); } @@ -800,13 +802,14 @@ static bool ux500_busy_complete(struct mmci_host *host, struct mmc_command *cmd, ux500_busy_clear_mask_done(host); } else { dev_dbg(mmc_dev(host->mmc), - "busy status still asserted when handling busy end IRQ - will keep waiting\n"); + "busy status still asserted when handling busy end IRQ - will keep waiting CMD%02x\n", + cmd->opcode); } break; default: - dev_dbg(mmc_dev(host->mmc), "fell through on state %d\n", - host->busy_state); + dev_dbg(mmc_dev(host->mmc), "fell through on state %d, CMD%02x\n", + host->busy_state, cmd->opcode); break; } @@ -1533,6 +1536,20 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, } } +static char *ux500_state_str(struct mmci_host *host) +{ + switch (host->busy_state) { + case MMCI_BUSY_WAITING_FOR_START_IRQ: + return "waiting for start IRQ"; + case MMCI_BUSY_WAITING_FOR_END_IRQ: + return "waiting for end IRQ"; + case MMCI_BUSY_DONE: + return "not waiting for IRQs"; + default: + return "unknown"; + } +} + /* * This busy timeout worker is used to "kick" the command IRQ if a * busy detect IRQ fails to appear in reasonable time. Only used on @@ -1548,12 +1565,18 @@ static void ux500_busy_timeout_work(struct work_struct *work) spin_lock_irqsave(&host->lock, flags); if (host->cmd) { - dev_dbg(mmc_dev(host->mmc), "timeout waiting for busy IRQ\n"); - /* If we are still busy let's tag on a cmd-timeout error. */ status = readl(host->base + MMCISTATUS); - if (status & host->variant->busy_detect_flag) + if (status & host->variant->busy_detect_flag) { status |= MCI_CMDTIMEOUT; + dev_err(mmc_dev(host->mmc), + "timeout in state %s still busy with CMD%02x\n", + ux500_state_str(host), host->cmd->opcode); + } else { + dev_err(mmc_dev(host->mmc), + "timeout in state %s waiting for busy CMD%02x\n", + ux500_state_str(host), host->cmd->opcode); + } mmci_cmd_irq(host, host->cmd, status); } diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c index 2d002c81dcf3..5cfdd3a86e54 100644 --- a/drivers/mmc/host/moxart-mmc.c +++ b/drivers/mmc/host/moxart-mmc.c @@ -338,13 +338,7 @@ static void moxart_transfer_pio(struct moxart_host *host) return; } for (len = 0; len < remain && len < host->fifo_width;) { - /* SCR data must be read in big endian. */ - if (data->mrq->cmd->opcode == SD_APP_SEND_SCR) - *sgp = ioread32be(host->base + - REG_DATA_WINDOW); - else - *sgp = ioread32(host->base + - REG_DATA_WINDOW); + *sgp = ioread32(host->base + REG_DATA_WINDOW); sgp++; len += 4; } @@ -693,13 +687,11 @@ out_mmc: return ret; } -static int moxart_remove(struct platform_device *pdev) +static void moxart_remove(struct platform_device *pdev) { struct mmc_host *mmc = dev_get_drvdata(&pdev->dev); struct moxart_host *host = mmc_priv(mmc); - dev_set_drvdata(&pdev->dev, NULL); - if (!IS_ERR_OR_NULL(host->dma_chan_tx)) dma_release_channel(host->dma_chan_tx); if (!IS_ERR_OR_NULL(host->dma_chan_rx)) @@ -711,8 +703,6 @@ static int moxart_remove(struct platform_device *pdev) writel(readl(host->base + REG_CLOCK_CONTROL) | CLK_OFF, host->base + REG_CLOCK_CONTROL); mmc_free_host(mmc); - - return 0; } static const struct of_device_id moxart_mmc_match[] = { @@ -724,7 +714,7 @@ MODULE_DEVICE_TABLE(of, moxart_mmc_match); static struct platform_driver moxart_mmc_driver = { .probe = moxart_probe, - .remove = moxart_remove, + .remove_new = moxart_remove, .driver = { .name = "mmc-moxart", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 02403ff99e0d..5392200cfdf7 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -12,9 +12,7 @@ #include <linux/iopoll.h> #include <linux/ioport.h> #include <linux/irq.h> -#include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> +#include <linux/of.h> #include <linux/of_gpio.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> @@ -2887,7 +2885,7 @@ host_free: return ret; } -static int msdc_drv_remove(struct platform_device *pdev) +static void msdc_drv_remove(struct platform_device *pdev) { struct mmc_host *mmc; struct msdc_host *host; @@ -2911,8 +2909,6 @@ static int msdc_drv_remove(struct platform_device *pdev) host->dma.bd, host->dma.bd_addr); mmc_free_host(mmc); - - return 0; } static void msdc_save_reg(struct msdc_host *host) @@ -3054,7 +3050,7 @@ static const struct dev_pm_ops msdc_dev_pm_ops = { static struct platform_driver mt_msdc_driver = { .probe = msdc_drv_probe, - .remove = msdc_drv_remove, + .remove_new = msdc_drv_remove, .driver = { .name = "mtk-msdc", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index b4f6a0a2fcb5..ca01b7d204ba 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c @@ -796,7 +796,7 @@ out: return ret; } -static int mvsd_remove(struct platform_device *pdev) +static void mvsd_remove(struct platform_device *pdev) { struct mmc_host *mmc = platform_get_drvdata(pdev); @@ -809,8 +809,6 @@ static int mvsd_remove(struct platform_device *pdev) if (!IS_ERR(host->clk)) clk_disable_unprepare(host->clk); mmc_free_host(mmc); - - return 0; } static const struct of_device_id mvsdio_dt_ids[] = { @@ -821,7 +819,7 @@ MODULE_DEVICE_TABLE(of, mvsdio_dt_ids); static struct platform_driver mvsd_driver = { .probe = mvsd_probe, - .remove = mvsd_remove, + .remove_new = mvsd_remove, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 668f865f3efb..5b3ab0e20505 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -31,7 +31,6 @@ #include <linux/dmaengine.h> #include <linux/types.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_dma.h> #include <linux/mmc/slot-gpio.h> @@ -989,7 +988,6 @@ static int mxcmci_probe(struct platform_device *pdev) pr_info("i.MX/MPC512x SDHC driver\n"); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; @@ -1000,7 +998,7 @@ static int mxcmci_probe(struct platform_device *pdev) host = mmc_priv(mmc); - host->base = devm_ioremap_resource(&pdev->dev, res); + host->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(host->base)) { ret = PTR_ERR(host->base); goto out_free; @@ -1164,7 +1162,7 @@ out_free: return ret; } -static int mxcmci_remove(struct platform_device *pdev) +static void mxcmci_remove(struct platform_device *pdev) { struct mmc_host *mmc = platform_get_drvdata(pdev); struct mxcmci_host *host = mmc_priv(mmc); @@ -1181,8 +1179,6 @@ static int mxcmci_remove(struct platform_device *pdev) clk_disable_unprepare(host->clk_ipg); mmc_free_host(mmc); - - return 0; } static int mxcmci_suspend(struct device *dev) @@ -1216,7 +1212,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(mxcmci_pm_ops, mxcmci_suspend, mxcmci_resume); static struct platform_driver mxcmci_driver = { .probe = mxcmci_probe, - .remove = mxcmci_remove, + .remove_new = mxcmci_remove, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 8c3655d3be96..6751da9b60f9 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -11,7 +11,6 @@ #include <linux/init.h> #include <linux/ioport.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/interrupt.h> @@ -674,7 +673,7 @@ out_mmc_free: return ret; } -static int mxs_mmc_remove(struct platform_device *pdev) +static void mxs_mmc_remove(struct platform_device *pdev) { struct mmc_host *mmc = platform_get_drvdata(pdev); struct mxs_mmc_host *host = mmc_priv(mmc); @@ -688,8 +687,6 @@ static int mxs_mmc_remove(struct platform_device *pdev) clk_disable_unprepare(ssp->clk); mmc_free_host(mmc); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -717,7 +714,7 @@ static SIMPLE_DEV_PM_OPS(mxs_mmc_pm_ops, mxs_mmc_suspend, mxs_mmc_resume); static struct platform_driver mxs_mmc_driver = { .probe = mxs_mmc_probe, - .remove = mxs_mmc_remove, + .remove_new = mxs_mmc_remove, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 6a259563690d..9fb8995b43a1 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -1506,7 +1506,7 @@ err_free_iclk: return ret; } -static int mmc_omap_remove(struct platform_device *pdev) +static void mmc_omap_remove(struct platform_device *pdev) { struct mmc_omap_host *host = platform_get_drvdata(pdev); int i; @@ -1532,8 +1532,6 @@ static int mmc_omap_remove(struct platform_device *pdev) dma_release_channel(host->dma_rx); destroy_workqueue(host->mmc_omap_wq); - - return 0; } #if IS_BUILTIN(CONFIG_OF) @@ -1546,7 +1544,7 @@ MODULE_DEVICE_TABLE(of, mmc_omap_match); static struct platform_driver mmc_omap_driver = { .probe = mmc_omap_probe, - .remove = mmc_omap_remove, + .remove_new = mmc_omap_remove, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 1e0f2d7774bd..e120aeb869b8 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1790,14 +1790,11 @@ static int omap_hsmmc_probe(struct platform_device *pdev) return -ENXIO; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENXIO; irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(base)) return PTR_ERR(base); @@ -1982,7 +1979,7 @@ err: return ret; } -static int omap_hsmmc_remove(struct platform_device *pdev) +static void omap_hsmmc_remove(struct platform_device *pdev) { struct omap_hsmmc_host *host = platform_get_drvdata(pdev); @@ -2000,8 +1997,6 @@ static int omap_hsmmc_remove(struct platform_device *pdev) clk_disable_unprepare(host->dbclk); mmc_free_host(host->mmc); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -2126,7 +2121,7 @@ static const struct dev_pm_ops omap_hsmmc_dev_pm_ops = { static struct platform_driver omap_hsmmc_driver = { .probe = omap_hsmmc_probe, - .remove = omap_hsmmc_remove, + .remove_new = omap_hsmmc_remove, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/owl-mmc.c b/drivers/mmc/host/owl-mmc.c index 1bf22b08b373..fc08f25c34eb 100644 --- a/drivers/mmc/host/owl-mmc.c +++ b/drivers/mmc/host/owl-mmc.c @@ -16,8 +16,9 @@ #include <linux/interrupt.h> #include <linux/mmc/host.h> #include <linux/mmc/slot-gpio.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/reset.h> #include <linux/spinlock.h> @@ -667,7 +668,7 @@ err_free_host: return ret; } -static int owl_mmc_remove(struct platform_device *pdev) +static void owl_mmc_remove(struct platform_device *pdev) { struct mmc_host *mmc = platform_get_drvdata(pdev); struct owl_mmc_host *owl_host = mmc_priv(mmc); @@ -676,8 +677,6 @@ static int owl_mmc_remove(struct platform_device *pdev) disable_irq(owl_host->irq); dma_release_channel(owl_host->dma); mmc_free_host(mmc); - - return 0; } static const struct of_device_id owl_mmc_of_match[] = { @@ -693,7 +692,7 @@ static struct platform_driver owl_mmc_driver = { .of_match_table = owl_mmc_of_match, }, .probe = owl_mmc_probe, - .remove = owl_mmc_remove, + .remove_new = owl_mmc_remove, }; module_platform_driver(owl_mmc_driver); diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 2a988f942b6c..fae3192c3a14 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -30,7 +30,6 @@ #include <linux/gpio/consumer.h> #include <linux/gfp.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/soc/pxa/cpu.h> #include <linux/sizes.h> @@ -612,7 +611,6 @@ static int pxamci_probe(struct platform_device *pdev) struct resource *r; int ret, irq; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; @@ -685,14 +683,14 @@ static int pxamci_probe(struct platform_device *pdev) } spin_lock_init(&host->lock); - host->res = r; host->imask = MMC_I_MASK_ALL; - host->base = devm_ioremap_resource(dev, r); + host->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r); if (IS_ERR(host->base)) { ret = PTR_ERR(host->base); goto out; } + host->res = r; /* * Ensure that the host controller is shut down, and setup @@ -784,7 +782,7 @@ out: return ret; } -static int pxamci_remove(struct platform_device *pdev) +static void pxamci_remove(struct platform_device *pdev) { struct mmc_host *mmc = platform_get_drvdata(pdev); @@ -808,13 +806,11 @@ static int pxamci_remove(struct platform_device *pdev) mmc_free_host(mmc); } - - return 0; } static struct platform_driver pxamci_driver = { .probe = pxamci_probe, - .remove = pxamci_remove, + .remove_new = pxamci_remove, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h index 68da3da9e2e5..c1fb9740eab0 100644 --- a/drivers/mmc/host/renesas_sdhi.h +++ b/drivers/mmc/host/renesas_sdhi.h @@ -101,5 +101,5 @@ int renesas_sdhi_probe(struct platform_device *pdev, const struct tmio_mmc_dma_ops *dma_ops, const struct renesas_sdhi_of_data *of_data, const struct renesas_sdhi_quirks *quirks); -int renesas_sdhi_remove(struct platform_device *pdev); +void renesas_sdhi_remove(struct platform_device *pdev); #endif diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 345934e4f59e..c675dec587ef 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -983,12 +983,12 @@ int renesas_sdhi_probe(struct platform_device *pdev, } - host->write16_hook = renesas_sdhi_write16_hook; - host->clk_enable = renesas_sdhi_clk_enable; - host->clk_disable = renesas_sdhi_clk_disable; - host->set_clock = renesas_sdhi_set_clock; - host->multi_io_quirk = renesas_sdhi_multi_io_quirk; - host->dma_ops = dma_ops; + host->write16_hook = renesas_sdhi_write16_hook; + host->clk_enable = renesas_sdhi_clk_enable; + host->clk_disable = renesas_sdhi_clk_disable; + host->set_clock = renesas_sdhi_set_clock; + host->multi_io_quirk = renesas_sdhi_multi_io_quirk; + host->dma_ops = dma_ops; if (sdhi_has_quirk(priv, hs400_disabled)) host->mmc->caps2 &= ~(MMC_CAP2_HS400 | MMC_CAP2_HS400_ES); @@ -1006,6 +1006,8 @@ int renesas_sdhi_probe(struct platform_device *pdev, host->sdcard_irq_setbit_mask = TMIO_STAT_ALWAYS_SET_27; host->sdcard_irq_mask_all = TMIO_MASK_ALL_RCAR2; host->reset = renesas_sdhi_reset; + } else { + host->sdcard_irq_mask_all = TMIO_MASK_ALL; } /* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */ @@ -1100,9 +1102,7 @@ int renesas_sdhi_probe(struct platform_device *pdev, host->ops.hs400_complete = renesas_sdhi_hs400_complete; } - ret = tmio_mmc_host_probe(host); - if (ret < 0) - goto edisclk; + sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, host->sdcard_irq_mask_all); num_irqs = platform_irq_count(pdev); if (num_irqs < 0) { @@ -1129,6 +1129,10 @@ int renesas_sdhi_probe(struct platform_device *pdev, goto eirq; } + ret = tmio_mmc_host_probe(host); + if (ret < 0) + goto edisclk; + dev_info(&pdev->dev, "%s base at %pa, max clock rate %u MHz\n", mmc_hostname(host->mmc), &res->start, host->mmc->f_max / 1000000); @@ -1145,15 +1149,13 @@ efree: } EXPORT_SYMBOL_GPL(renesas_sdhi_probe); -int renesas_sdhi_remove(struct platform_device *pdev) +void renesas_sdhi_remove(struct platform_device *pdev) { struct tmio_mmc_host *host = platform_get_drvdata(pdev); tmio_mmc_host_remove(host); renesas_sdhi_clk_disable(host); tmio_mmc_host_free(host); - - return 0; } EXPORT_SYMBOL_GPL(renesas_sdhi_remove); diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index 9ab813903b2c..53d34c3eddce 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -15,7 +15,8 @@ #include <linux/mmc/host.h> #include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/pagemap.h> #include <linux/scatterlist.h> #include <linux/sys_soc.h> @@ -609,7 +610,7 @@ static struct platform_driver renesas_internal_dmac_sdhi_driver = { .of_match_table = renesas_sdhi_internal_dmac_of_match, }, .probe = renesas_sdhi_internal_dmac_probe, - .remove = renesas_sdhi_remove, + .remove_new = renesas_sdhi_remove, }; module_platform_driver(renesas_internal_dmac_sdhi_driver); diff --git a/drivers/mmc/host/renesas_sdhi_sys_dmac.c b/drivers/mmc/host/renesas_sdhi_sys_dmac.c index b559ad38b667..9cf7f9feab72 100644 --- a/drivers/mmc/host/renesas_sdhi_sys_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_sys_dmac.c @@ -15,7 +15,8 @@ #include <linux/mmc/host.h> #include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/pagemap.h> #include <linux/scatterlist.h> #include <linux/sys_soc.h> @@ -470,7 +471,7 @@ static struct platform_driver renesas_sys_dmac_sdhi_driver = { .of_match_table = renesas_sdhi_sys_dmac_of_match, }, .probe = renesas_sdhi_sys_dmac_probe, - .remove = renesas_sdhi_remove, + .remove_new = renesas_sdhi_remove, }; module_platform_driver(renesas_sys_dmac_sdhi_driver); diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index 8098726dcc0b..87d78432a1e0 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c @@ -1523,15 +1523,12 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev) return 0; } -static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev) +static void rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev) { struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); struct rtsx_pcr *pcr; struct mmc_host *mmc; - if (!host) - return 0; - pcr = host->pcr; pcr->slots[RTSX_SD_CARD].p_dev = NULL; pcr->slots[RTSX_SD_CARD].card_event = NULL; @@ -1566,8 +1563,6 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev) dev_dbg(&(pdev->dev), ": Realtek PCI-E SDMMC controller has been removed\n"); - - return 0; } static const struct platform_device_id rtsx_pci_sdmmc_ids[] = { @@ -1581,7 +1576,7 @@ MODULE_DEVICE_TABLE(platform, rtsx_pci_sdmmc_ids); static struct platform_driver rtsx_pci_sdmmc_driver = { .probe = rtsx_pci_sdmmc_drv_probe, - .remove = rtsx_pci_sdmmc_drv_remove, + .remove_new = rtsx_pci_sdmmc_drv_remove, .id_table = rtsx_pci_sdmmc_ids, .driver = { .name = DRV_NAME_RTSX_PCI_SDMMC, diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c index 2c650cd58693..ded9b6849e35 100644 --- a/drivers/mmc/host/rtsx_usb_sdmmc.c +++ b/drivers/mmc/host/rtsx_usb_sdmmc.c @@ -1379,13 +1379,13 @@ static int rtsx_usb_sdmmc_drv_probe(struct platform_device *pdev) return 0; } -static int rtsx_usb_sdmmc_drv_remove(struct platform_device *pdev) +static void rtsx_usb_sdmmc_drv_remove(struct platform_device *pdev) { struct rtsx_usb_sdmmc *host = platform_get_drvdata(pdev); struct mmc_host *mmc; if (!host) - return 0; + return; mmc = host->mmc; host->host_removal = true; @@ -1415,8 +1415,6 @@ static int rtsx_usb_sdmmc_drv_remove(struct platform_device *pdev) dev_dbg(&(pdev->dev), ": Realtek USB SD/MMC module has been removed\n"); - - return 0; } #ifdef CONFIG_PM @@ -1455,7 +1453,7 @@ MODULE_DEVICE_TABLE(platform, rtsx_usb_sdmmc_ids); static struct platform_driver rtsx_usb_sdmmc_driver = { .probe = rtsx_usb_sdmmc_drv_probe, - .remove = rtsx_usb_sdmmc_drv_remove, + .remove_new = rtsx_usb_sdmmc_drv_remove, .id_table = rtsx_usb_sdmmc_ids, .driver = { .name = "rtsx_usb_sdmmc", diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index edf2e6c14dc6..acf5fc3ad7e4 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -917,7 +917,7 @@ err_free: return err; } -static int sdhci_acpi_remove(struct platform_device *pdev) +static void sdhci_acpi_remove(struct platform_device *pdev) { struct sdhci_acpi_host *c = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; @@ -939,8 +939,6 @@ static int sdhci_acpi_remove(struct platform_device *pdev) c->slot->free_slot(pdev); sdhci_free_host(c->host); - - return 0; } static void __maybe_unused sdhci_acpi_reset_signal_voltage_if_needed( @@ -1033,7 +1031,7 @@ static struct platform_driver sdhci_acpi_driver = { .pm = &sdhci_acpi_pm_ops, }, .probe = sdhci_acpi_probe, - .remove = sdhci_acpi_remove, + .remove_new = sdhci_acpi_remove, }; module_platform_driver(sdhci_acpi_driver); diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c index 6a93a54fe067..cb9152c6a65d 100644 --- a/drivers/mmc/host/sdhci-bcm-kona.c +++ b/drivers/mmc/host/sdhci-bcm-kona.c @@ -11,7 +11,6 @@ #include <linux/clk.h> #include <linux/regulator/consumer.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/mmc/slot-gpio.h> #include "sdhci-pltfm.h" @@ -311,6 +310,16 @@ err_pltfm_free: return ret; } +static void sdhci_bcm_kona_remove(struct platform_device *pdev) +{ + struct sdhci_host *host = platform_get_drvdata(pdev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct clk *clk = pltfm_host->clk; + + sdhci_pltfm_remove(pdev); + clk_disable_unprepare(clk); +} + static struct platform_driver sdhci_bcm_kona_driver = { .driver = { .name = "sdhci-kona", @@ -319,7 +328,7 @@ static struct platform_driver sdhci_bcm_kona_driver = { .of_match_table = sdhci_bcm_kona_of_match, }, .probe = sdhci_bcm_kona_probe, - .remove = sdhci_pltfm_unregister, + .remove_new = sdhci_bcm_kona_remove, }; module_platform_driver(sdhci_bcm_kona_driver); diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c index 4c22337199cf..c23251bb95f3 100644 --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -264,23 +264,17 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "Probe found match for %s\n", match->compatible); - clk = devm_clk_get_optional(&pdev->dev, NULL); + clk = devm_clk_get_optional_enabled(&pdev->dev, NULL); if (IS_ERR(clk)) return dev_err_probe(&pdev->dev, PTR_ERR(clk), - "Failed to get clock from Device Tree\n"); - - res = clk_prepare_enable(clk); - if (res) - return res; + "Failed to get and enable clock from Device Tree\n"); memset(&brcmstb_pdata, 0, sizeof(brcmstb_pdata)); brcmstb_pdata.ops = match_priv->ops; host = sdhci_pltfm_init(pdev, &brcmstb_pdata, sizeof(struct sdhci_brcmstb_priv)); - if (IS_ERR(host)) { - res = PTR_ERR(host); - goto err_clk; - } + if (IS_ERR(host)) + return PTR_ERR(host); pltfm_host = sdhci_priv(host); priv = sdhci_pltfm_priv(pltfm_host); @@ -369,9 +363,7 @@ add_host: err: sdhci_pltfm_free(pdev); -err_clk: clk_disable_unprepare(base_clk); - clk_disable_unprepare(clk); return res; } @@ -430,7 +422,7 @@ static struct platform_driver sdhci_brcmstb_driver = { .of_match_table = of_match_ptr(sdhci_brcm_of_match), }, .probe = sdhci_brcmstb_probe, - .remove = sdhci_pltfm_unregister, + .remove_new = sdhci_pltfm_remove, .shutdown = sdhci_brcmstb_shutdown, }; diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c index d2f625054689..be1505e8c536 100644 --- a/drivers/mmc/host/sdhci-cadence.c +++ b/drivers/mmc/host/sdhci-cadence.c @@ -11,7 +11,7 @@ #include <linux/mmc/host.h> #include <linux/mmc/mmc.h> #include <linux/of.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> #include <linux/reset.h> #include "sdhci-pltfm.h" @@ -487,14 +487,10 @@ static int sdhci_cdns_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; static const u16 version = SDHCI_SPEC_400 << SDHCI_SPEC_VER_SHIFT; - clk = devm_clk_get(dev, NULL); + clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(clk)) return PTR_ERR(clk); - ret = clk_prepare_enable(clk); - if (ret) - return ret; - data = of_device_get_match_data(dev); if (!data) data = &sdhci_cdns_drv_data; @@ -502,10 +498,8 @@ static int sdhci_cdns_probe(struct platform_device *pdev) nr_phy_params = sdhci_cdns_phy_param_count(dev->of_node); host = sdhci_pltfm_init(pdev, &data->pltfm_data, struct_size(priv, phy_params, nr_phy_params)); - if (IS_ERR(host)) { - ret = PTR_ERR(host); - goto disable_clk; - } + if (IS_ERR(host)) + return PTR_ERR(host); pltfm_host = sdhci_priv(host); pltfm_host->clk = clk; @@ -556,9 +550,6 @@ static int sdhci_cdns_probe(struct platform_device *pdev) return 0; free: sdhci_pltfm_free(pdev); -disable_clk: - clk_disable_unprepare(clk); - return ret; } @@ -617,7 +608,7 @@ static struct platform_driver sdhci_cdns_driver = { .of_match_table = sdhci_cdns_match, }, .probe = sdhci_cdns_probe, - .remove = sdhci_pltfm_unregister, + .remove_new = sdhci_pltfm_remove, }; module_platform_driver(sdhci_cdns_driver); diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index 5e5bf82e5976..88ec23417808 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c @@ -75,10 +75,7 @@ static int sdhci_dove_probe(struct platform_device *pdev) return PTR_ERR(host); pltfm_host = sdhci_priv(host); - pltfm_host->clk = devm_clk_get(&pdev->dev, NULL); - - if (!IS_ERR(pltfm_host->clk)) - clk_prepare_enable(pltfm_host->clk); + pltfm_host->clk = devm_clk_get_enabled(&pdev->dev, NULL); ret = mmc_of_parse(host->mmc); if (ret) @@ -91,7 +88,6 @@ static int sdhci_dove_probe(struct platform_device *pdev) return 0; err_sdhci_add: - clk_disable_unprepare(pltfm_host->clk); sdhci_pltfm_free(pdev); return ret; } @@ -110,7 +106,7 @@ static struct platform_driver sdhci_dove_driver = { .of_match_table = sdhci_dove_of_match_table, }, .probe = sdhci_dove_probe, - .remove = sdhci_pltfm_unregister, + .remove_new = sdhci_pltfm_remove, }; module_platform_driver(sdhci_dove_driver); diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index eebf94604a7f..3b8030f3552a 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -22,7 +22,7 @@ #include <linux/mmc/sdio.h> #include <linux/mmc/slot-gpio.h> #include <linux/of.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> #include <linux/pinctrl/consumer.h> #include <linux/pm_runtime.h> #include "sdhci-cqhci.h" @@ -171,8 +171,8 @@ #define ESDHC_FLAG_HS400 BIT(9) /* * The IP has errata ERR010450 - * uSDHC: Due to the I/O timing limit, for SDR mode, SD card clock can't - * exceed 150MHz, for DDR mode, SD card clock can't exceed 45MHz. + * uSDHC: At 1.8V due to the I/O timing limit, for SDR mode, SD card + * clock can't exceed 150MHz, for DDR mode, SD card clock can't exceed 45MHz. */ #define ESDHC_FLAG_ERR010450 BIT(10) /* The IP supports HS400ES mode */ @@ -961,7 +961,8 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host, | ESDHC_CLOCK_MASK); sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); - if (imx_data->socdata->flags & ESDHC_FLAG_ERR010450) { + if ((imx_data->socdata->flags & ESDHC_FLAG_ERR010450) && + (!(host->quirks2 & SDHCI_QUIRK2_NO_1_8_V))) { unsigned int max_clock; max_clock = imx_data->is_ddr ? 45000000 : 150000000; @@ -1802,7 +1803,7 @@ free_sdhci: return err; } -static int sdhci_esdhc_imx_remove(struct platform_device *pdev) +static void sdhci_esdhc_imx_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -1824,8 +1825,6 @@ static int sdhci_esdhc_imx_remove(struct platform_device *pdev) cpu_latency_qos_remove_request(&imx_data->pm_qos_req); sdhci_pltfm_free(pdev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1986,7 +1985,7 @@ static struct platform_driver sdhci_esdhc_imx_driver = { .pm = &sdhci_esdhc_pmops, }, .probe = sdhci_esdhc_imx_probe, - .remove = sdhci_esdhc_imx_remove, + .remove_new = sdhci_esdhc_imx_remove, }; module_platform_driver(sdhci_esdhc_imx_driver); diff --git a/drivers/mmc/host/sdhci-esdhc-mcf.c b/drivers/mmc/host/sdhci-esdhc-mcf.c index 05926bf5ecf9..a07f8333cd6b 100644 --- a/drivers/mmc/host/sdhci-esdhc-mcf.c +++ b/drivers/mmc/host/sdhci-esdhc-mcf.c @@ -489,7 +489,7 @@ err_exit: return err; } -static int sdhci_esdhc_mcf_remove(struct platform_device *pdev) +static void sdhci_esdhc_mcf_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -502,8 +502,6 @@ static int sdhci_esdhc_mcf_remove(struct platform_device *pdev) clk_disable_unprepare(mcf_data->clk_per); sdhci_pltfm_free(pdev); - - return 0; } static struct platform_driver sdhci_esdhc_mcf_driver = { @@ -512,7 +510,7 @@ static struct platform_driver sdhci_esdhc_mcf_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .probe = sdhci_esdhc_mcf_probe, - .remove = sdhci_esdhc_mcf_remove, + .remove_new = sdhci_esdhc_mcf_remove, }; module_platform_driver(sdhci_esdhc_mcf_driver); diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c index 86eb0045515e..10235fdff246 100644 --- a/drivers/mmc/host/sdhci-iproc.c +++ b/drivers/mmc/host/sdhci-iproc.c @@ -10,7 +10,7 @@ #include <linux/module.h> #include <linux/mmc/host.h> #include <linux/of.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> #include "sdhci-pltfm.h" struct sdhci_iproc_data { @@ -386,16 +386,11 @@ static int sdhci_iproc_probe(struct platform_device *pdev) host->mmc->caps |= iproc_host->data->mmc_caps; if (dev->of_node) { - pltfm_host->clk = devm_clk_get(dev, NULL); + pltfm_host->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(pltfm_host->clk)) { ret = PTR_ERR(pltfm_host->clk); goto err; } - ret = clk_prepare_enable(pltfm_host->clk); - if (ret) { - dev_err(dev, "failed to enable host clk\n"); - goto err; - } } if (iproc_host->data->missing_caps) { @@ -406,13 +401,10 @@ static int sdhci_iproc_probe(struct platform_device *pdev) ret = sdhci_add_host(host); if (ret) - goto err_clk; + goto err; return 0; -err_clk: - if (dev->of_node) - clk_disable_unprepare(pltfm_host->clk); err: sdhci_pltfm_free(pdev); return ret; @@ -432,7 +424,7 @@ static struct platform_driver sdhci_iproc_driver = { .pm = &sdhci_pltfm_pmops, }, .probe = sdhci_iproc_probe, - .remove = sdhci_pltfm_unregister, + .remove_new = sdhci_pltfm_remove, .shutdown = sdhci_iproc_shutdown, }; module_platform_driver(sdhci_iproc_driver); diff --git a/drivers/mmc/host/sdhci-milbeaut.c b/drivers/mmc/host/sdhci-milbeaut.c index 148b37ac6564..83706edc9796 100644 --- a/drivers/mmc/host/sdhci-milbeaut.c +++ b/drivers/mmc/host/sdhci-milbeaut.c @@ -313,7 +313,7 @@ err: return ret; } -static int sdhci_milbeaut_remove(struct platform_device *pdev) +static void sdhci_milbeaut_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct f_sdhost_priv *priv = sdhci_priv(host); @@ -326,18 +326,16 @@ static int sdhci_milbeaut_remove(struct platform_device *pdev) sdhci_free_host(host); platform_set_drvdata(pdev, NULL); - - return 0; } static struct platform_driver sdhci_milbeaut_driver = { .driver = { .name = "sdhci-milbeaut", .probe_type = PROBE_PREFER_ASYNCHRONOUS, - .of_match_table = of_match_ptr(mlb_dt_ids), + .of_match_table = mlb_dt_ids, }, .probe = sdhci_milbeaut_probe, - .remove = sdhci_milbeaut_remove, + .remove_new = sdhci_milbeaut_remove, }; module_platform_driver(sdhci_milbeaut_driver); diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 1c935b5bafe1..668e0aceeeba 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -6,7 +6,6 @@ */ #include <linux/module.h> -#include <linux/of_device.h> #include <linux/delay.h> #include <linux/mmc/mmc.h> #include <linux/pm_runtime.h> @@ -15,6 +14,7 @@ #include <linux/iopoll.h> #include <linux/regulator/consumer.h> #include <linux/interconnect.h> +#include <linux/of.h> #include <linux/pinctrl/consumer.h> #include <linux/reset.h> @@ -2668,7 +2668,7 @@ pltfm_free: return ret; } -static int sdhci_msm_remove(struct platform_device *pdev) +static void sdhci_msm_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -2687,7 +2687,6 @@ static int sdhci_msm_remove(struct platform_device *pdev) if (!IS_ERR(msm_host->bus_clk)) clk_disable_unprepare(msm_host->bus_clk); sdhci_pltfm_free(pdev); - return 0; } static __maybe_unused int sdhci_msm_runtime_suspend(struct device *dev) @@ -2740,7 +2739,7 @@ static const struct dev_pm_ops sdhci_msm_pm_ops = { static struct platform_driver sdhci_msm_driver = { .probe = sdhci_msm_probe, - .remove = sdhci_msm_remove, + .remove_new = sdhci_msm_remove, .driver = { .name = "sdhci_msm", .of_match_table = sdhci_msm_dt_match, diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index 294dd605fd2b..5edd024347bd 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -18,11 +18,11 @@ #include <linux/clk-provider.h> #include <linux/mfd/syscon.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/phy/phy.h> #include <linux/regmap.h> #include <linux/reset.h> -#include <linux/of.h> #include <linux/firmware/xlnx-zynqmp.h> #include "cqhci.h" @@ -2016,12 +2016,13 @@ err_pltfm_free: return ret; } -static int sdhci_arasan_remove(struct platform_device *pdev) +static void sdhci_arasan_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host); struct clk *clk_ahb = sdhci_arasan->clk_ahb; + struct clk *clk_xin = pltfm_host->clk; if (!IS_ERR(sdhci_arasan->phy)) { if (sdhci_arasan->is_phy_on) @@ -2031,11 +2032,10 @@ static int sdhci_arasan_remove(struct platform_device *pdev) sdhci_arasan_unregister_sdclk(&pdev->dev); - sdhci_pltfm_unregister(pdev); + sdhci_pltfm_remove(pdev); + clk_disable_unprepare(clk_xin); clk_disable_unprepare(clk_ahb); - - return 0; } static struct platform_driver sdhci_arasan_driver = { @@ -2046,7 +2046,7 @@ static struct platform_driver sdhci_arasan_driver = { .pm = &sdhci_arasan_dev_pm_ops, }, .probe = sdhci_arasan_probe, - .remove = sdhci_arasan_remove, + .remove_new = sdhci_arasan_remove, }; module_platform_driver(sdhci_arasan_driver); diff --git a/drivers/mmc/host/sdhci-of-aspeed.c b/drivers/mmc/host/sdhci-of-aspeed.c index 25b4073f698b..42d54532cabe 100644 --- a/drivers/mmc/host/sdhci-of-aspeed.c +++ b/drivers/mmc/host/sdhci-of-aspeed.c @@ -450,22 +450,19 @@ err_pltfm_free: return ret; } -static int aspeed_sdhci_remove(struct platform_device *pdev) +static void aspeed_sdhci_remove(struct platform_device *pdev) { struct sdhci_pltfm_host *pltfm_host; struct sdhci_host *host; - int dead = 0; host = platform_get_drvdata(pdev); pltfm_host = sdhci_priv(host); - sdhci_remove_host(host, dead); + sdhci_remove_host(host, 0); clk_disable_unprepare(pltfm_host->clk); sdhci_pltfm_free(pdev); - - return 0; } static const struct aspeed_sdhci_pdata ast2400_sdhci_pdata = { @@ -521,7 +518,7 @@ static struct platform_driver aspeed_sdhci_driver = { .of_match_table = aspeed_sdhci_of_match, }, .probe = aspeed_sdhci_probe, - .remove = aspeed_sdhci_remove, + .remove_new = aspeed_sdhci_remove, }; static int aspeed_sdc_probe(struct platform_device *pdev) @@ -574,13 +571,11 @@ err_clk: return ret; } -static int aspeed_sdc_remove(struct platform_device *pdev) +static void aspeed_sdc_remove(struct platform_device *pdev) { struct aspeed_sdc *sdc = dev_get_drvdata(&pdev->dev); clk_disable_unprepare(sdc->clk); - - return 0; } static const struct of_device_id aspeed_sdc_of_match[] = { @@ -600,7 +595,7 @@ static struct platform_driver aspeed_sdc_driver = { .of_match_table = aspeed_sdc_of_match, }, .probe = aspeed_sdc_probe, - .remove = aspeed_sdc_remove, + .remove_new = aspeed_sdc_remove, }; #if defined(CONFIG_MMC_SDHCI_OF_ASPEED_TEST) diff --git a/drivers/mmc/host/sdhci-of-at91.c b/drivers/mmc/host/sdhci-of-at91.c index cd0134580a90..23a9faad2ff8 100644 --- a/drivers/mmc/host/sdhci-of-at91.c +++ b/drivers/mmc/host/sdhci-of-at91.c @@ -17,7 +17,7 @@ #include <linux/mmc/slot-gpio.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> #include <linux/pm.h> #include <linux/pm_runtime.h> @@ -443,7 +443,7 @@ sdhci_pltfm_free: return ret; } -static int sdhci_at91_remove(struct platform_device *pdev) +static void sdhci_at91_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -456,13 +456,11 @@ static int sdhci_at91_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); - sdhci_pltfm_unregister(pdev); + sdhci_pltfm_remove(pdev); clk_disable_unprepare(gck); clk_disable_unprepare(hclock); clk_disable_unprepare(mainck); - - return 0; } static struct platform_driver sdhci_at91_driver = { @@ -473,7 +471,7 @@ static struct platform_driver sdhci_at91_driver = { .pm = &sdhci_at91_dev_pm_ops, }, .probe = sdhci_at91_probe, - .remove = sdhci_at91_remove, + .remove_new = sdhci_at91_remove, }; module_platform_driver(sdhci_at91_driver); diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index e68cd87998c8..3a3bae6948a8 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -14,7 +14,8 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/reset.h> #include <linux/sizes.h> @@ -548,9 +549,13 @@ static int dwcmshc_probe(struct platform_device *pdev) host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + err = sdhci_setup_host(host); if (err) - goto err_clk; + goto err_rpm; if (rk_priv) dwcmshc_rk35xx_postinit(host, priv); @@ -559,10 +564,15 @@ static int dwcmshc_probe(struct platform_device *pdev) if (err) goto err_setup_host; + pm_runtime_put(dev); + return 0; err_setup_host: sdhci_cleanup_host(host); +err_rpm: + pm_runtime_disable(dev); + pm_runtime_put_noidle(dev); err_clk: clk_disable_unprepare(pltfm_host->clk); clk_disable_unprepare(priv->bus_clk); @@ -574,7 +584,7 @@ free_pltfm: return err; } -static int dwcmshc_remove(struct platform_device *pdev) +static void dwcmshc_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -589,8 +599,6 @@ static int dwcmshc_remove(struct platform_device *pdev) clk_bulk_disable_unprepare(RK35xx_MAX_CLKS, rk_priv->rockchip_clks); sdhci_pltfm_free(pdev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -602,6 +610,8 @@ static int dwcmshc_suspend(struct device *dev) struct rk35xx_priv *rk_priv = priv->priv; int ret; + pm_runtime_resume(dev); + ret = sdhci_suspend_host(host); if (ret) return ret; @@ -632,21 +642,84 @@ static int dwcmshc_resume(struct device *dev) if (!IS_ERR(priv->bus_clk)) { ret = clk_prepare_enable(priv->bus_clk); if (ret) - return ret; + goto disable_clk; } if (rk_priv) { ret = clk_bulk_prepare_enable(RK35xx_MAX_CLKS, rk_priv->rockchip_clks); if (ret) - return ret; + goto disable_bus_clk; } - return sdhci_resume_host(host); + ret = sdhci_resume_host(host); + if (ret) + goto disable_rockchip_clks; + + return 0; + +disable_rockchip_clks: + if (rk_priv) + clk_bulk_disable_unprepare(RK35xx_MAX_CLKS, + rk_priv->rockchip_clks); +disable_bus_clk: + if (!IS_ERR(priv->bus_clk)) + clk_disable_unprepare(priv->bus_clk); +disable_clk: + clk_disable_unprepare(pltfm_host->clk); + return ret; } #endif -static SIMPLE_DEV_PM_OPS(dwcmshc_pmops, dwcmshc_suspend, dwcmshc_resume); +#ifdef CONFIG_PM + +static void dwcmshc_enable_card_clk(struct sdhci_host *host) +{ + u16 ctrl; + + ctrl = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + if ((ctrl & SDHCI_CLOCK_INT_EN) && !(ctrl & SDHCI_CLOCK_CARD_EN)) { + ctrl |= SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, ctrl, SDHCI_CLOCK_CONTROL); + } +} + +static void dwcmshc_disable_card_clk(struct sdhci_host *host) +{ + u16 ctrl; + + ctrl = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + if (ctrl & SDHCI_CLOCK_CARD_EN) { + ctrl &= ~SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, ctrl, SDHCI_CLOCK_CONTROL); + } +} + +static int dwcmshc_runtime_suspend(struct device *dev) +{ + struct sdhci_host *host = dev_get_drvdata(dev); + + dwcmshc_disable_card_clk(host); + + return 0; +} + +static int dwcmshc_runtime_resume(struct device *dev) +{ + struct sdhci_host *host = dev_get_drvdata(dev); + + dwcmshc_enable_card_clk(host); + + return 0; +} + +#endif + +static const struct dev_pm_ops dwcmshc_pmops = { + SET_SYSTEM_SLEEP_PM_OPS(dwcmshc_suspend, dwcmshc_resume) + SET_RUNTIME_PM_OPS(dwcmshc_runtime_suspend, + dwcmshc_runtime_resume, NULL) +}; static struct platform_driver sdhci_dwcmshc_driver = { .driver = { @@ -657,7 +730,7 @@ static struct platform_driver sdhci_dwcmshc_driver = { .pm = &dwcmshc_pmops, }, .probe = dwcmshc_probe, - .remove = dwcmshc_remove, + .remove_new = dwcmshc_remove, }; module_platform_driver(sdhci_dwcmshc_driver); diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 48ca1cf15b19..3ae9aa25745a 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -1521,7 +1521,7 @@ static struct platform_driver sdhci_esdhc_driver = { .pm = &esdhc_of_dev_pm_ops, }, .probe = sdhci_esdhc_probe, - .remove = sdhci_pltfm_unregister, + .remove_new = sdhci_pltfm_remove, }; module_platform_driver(sdhci_esdhc_driver); diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c index 12675797b296..9c1c0ce610ef 100644 --- a/drivers/mmc/host/sdhci-of-hlwd.c +++ b/drivers/mmc/host/sdhci-of-hlwd.c @@ -68,7 +68,7 @@ static const struct sdhci_pltfm_data sdhci_hlwd_pdata = { static int sdhci_hlwd_probe(struct platform_device *pdev) { - return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata, 0); + return sdhci_pltfm_init_and_add_host(pdev, &sdhci_hlwd_pdata, 0); } static const struct of_device_id sdhci_hlwd_of_match[] = { @@ -85,7 +85,7 @@ static struct platform_driver sdhci_hlwd_driver = { .pm = &sdhci_pltfm_pmops, }, .probe = sdhci_hlwd_probe, - .remove = sdhci_pltfm_unregister, + .remove_new = sdhci_pltfm_remove, }; module_platform_driver(sdhci_hlwd_driver); diff --git a/drivers/mmc/host/sdhci-of-sparx5.c b/drivers/mmc/host/sdhci-of-sparx5.c index 28e4ee69e100..64b77e7d14cd 100644 --- a/drivers/mmc/host/sdhci-of-sparx5.c +++ b/drivers/mmc/host/sdhci-of-sparx5.c @@ -13,9 +13,9 @@ #include <linux/delay.h> #include <linux/module.h> #include <linux/regmap.h> -#include <linux/of_device.h> #include <linux/mfd/syscon.h> #include <linux/dma-mapping.h> +#include <linux/of.h> #include "sdhci-pltfm.h" @@ -184,15 +184,12 @@ static int sdhci_sparx5_probe(struct platform_device *pdev) sdhci_sparx5 = sdhci_pltfm_priv(pltfm_host); sdhci_sparx5->host = host; - pltfm_host->clk = devm_clk_get(&pdev->dev, "core"); + pltfm_host->clk = devm_clk_get_enabled(&pdev->dev, "core"); if (IS_ERR(pltfm_host->clk)) { ret = PTR_ERR(pltfm_host->clk); - dev_err(&pdev->dev, "failed to get core clk: %d\n", ret); + dev_err(&pdev->dev, "failed to get and enable core clk: %d\n", ret); goto free_pltfm; } - ret = clk_prepare_enable(pltfm_host->clk); - if (ret) - goto free_pltfm; if (!of_property_read_u32(np, "microchip,clock-delay", &value) && (value > 0 && value <= MSHC_DLY_CC_MAX)) @@ -202,13 +199,13 @@ static int sdhci_sparx5_probe(struct platform_device *pdev) ret = mmc_of_parse(host->mmc); if (ret) - goto err_clk; + goto free_pltfm; sdhci_sparx5->cpu_ctrl = syscon_regmap_lookup_by_compatible(syscon); if (IS_ERR(sdhci_sparx5->cpu_ctrl)) { dev_err(&pdev->dev, "No CPU syscon regmap !\n"); ret = PTR_ERR(sdhci_sparx5->cpu_ctrl); - goto err_clk; + goto free_pltfm; } if (sdhci_sparx5->delay_clock >= 0) @@ -225,7 +222,7 @@ static int sdhci_sparx5_probe(struct platform_device *pdev) ret = sdhci_add_host(host); if (ret) - goto err_clk; + goto free_pltfm; /* Set AXI bus master to use un-cached access (for DMA) */ if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA) && @@ -239,8 +236,6 @@ static int sdhci_sparx5_probe(struct platform_device *pdev) return ret; -err_clk: - clk_disable_unprepare(pltfm_host->clk); free_pltfm: sdhci_pltfm_free(pdev); return ret; @@ -260,7 +255,7 @@ static struct platform_driver sdhci_sparx5_driver = { .pm = &sdhci_pltfm_pmops, }, .probe = sdhci_sparx5_probe, - .remove = sdhci_pltfm_unregister, + .remove_new = sdhci_pltfm_remove, }; module_platform_driver(sdhci_sparx5_driver); diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c index 8ed9256b83da..1e0bc7bace1b 100644 --- a/drivers/mmc/host/sdhci-omap.c +++ b/drivers/mmc/host/sdhci-omap.c @@ -11,7 +11,6 @@ #include <linux/mmc/slot-gpio.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> @@ -1394,7 +1393,7 @@ err_pltfm_free: return ret; } -static int sdhci_omap_remove(struct platform_device *pdev) +static void sdhci_omap_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct sdhci_host *host = platform_get_drvdata(pdev); @@ -1408,8 +1407,6 @@ static int sdhci_omap_remove(struct platform_device *pdev) /* Ensure device gets disabled despite userspace sysfs config */ pm_runtime_force_suspend(dev); sdhci_pltfm_free(pdev); - - return 0; } #ifdef CONFIG_PM @@ -1478,7 +1475,7 @@ static const struct dev_pm_ops sdhci_omap_dev_pm_ops = { static struct platform_driver sdhci_omap_driver = { .probe = sdhci_omap_probe, - .remove = sdhci_omap_remove, + .remove_new = sdhci_omap_remove, .driver = { .name = "sdhci-omap", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 1c2572c0f012..7c14feb5db77 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -1898,6 +1898,10 @@ static const struct pci_device_id pci_ids[] = { SDHCI_PCI_DEVICE(O2, SDS1, o2), SDHCI_PCI_DEVICE(O2, SEABIRD0, o2), SDHCI_PCI_DEVICE(O2, SEABIRD1, o2), + SDHCI_PCI_DEVICE(O2, GG8_9860, o2), + SDHCI_PCI_DEVICE(O2, GG8_9861, o2), + SDHCI_PCI_DEVICE(O2, GG8_9862, o2), + SDHCI_PCI_DEVICE(O2, GG8_9863, o2), SDHCI_PCI_DEVICE(ARASAN, PHY_EMMC, arasan), SDHCI_PCI_DEVICE(SYNOPSYS, DWC_MSHC, snps), SDHCI_PCI_DEVICE(GLI, 9750, gl9750), diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c index 620f52ad9667..7bfee28116af 100644 --- a/drivers/mmc/host/sdhci-pci-o2micro.c +++ b/drivers/mmc/host/sdhci-pci-o2micro.c @@ -21,6 +21,7 @@ * O2Micro device registers */ +#define O2_SD_PCIE_SWITCH 0x54 #define O2_SD_MISC_REG5 0x64 #define O2_SD_LD0_CTRL 0x68 #define O2_SD_DEV_CTRL 0x88 @@ -36,6 +37,7 @@ #define O2_SD_INF_MOD 0xF1 #define O2_SD_MISC_CTRL4 0xFC #define O2_SD_MISC_CTRL 0x1C0 +#define O2_SD_EXP_INT_REG 0x1E0 #define O2_SD_PWR_FORCE_L0 0x0002 #define O2_SD_TUNING_CTRL 0x300 #define O2_SD_PLL_SETTING 0x304 @@ -49,6 +51,9 @@ #define O2_SD_UHS2_L1_CTRL 0x35C #define O2_SD_FUNC_REG3 0x3E0 #define O2_SD_FUNC_REG4 0x3E4 +#define O2_SD_PARA_SET_REG1 0x444 +#define O2_SD_VDDX_CTRL_REG 0x508 +#define O2_SD_GPIO_CTRL_REG1 0x510 #define O2_SD_LED_ENABLE BIT(6) #define O2_SD_FREG0_LEDOFF BIT(13) #define O2_SD_SEL_DLL BIT(16) @@ -334,33 +339,45 @@ static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode) scratch |= O2_SD_PWR_FORCE_L0; sdhci_writew(host, scratch, O2_SD_MISC_CTRL); - /* Stop clk */ - reg_val = sdhci_readw(host, SDHCI_CLOCK_CONTROL); - reg_val &= ~SDHCI_CLOCK_CARD_EN; - sdhci_writew(host, reg_val, SDHCI_CLOCK_CONTROL); - - if ((host->timing == MMC_TIMING_MMC_HS200) || - (host->timing == MMC_TIMING_UHS_SDR104)) { - /* UnLock WP */ - pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8); - scratch_8 &= 0x7f; - pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); - - /* Set pcr 0x354[16] to choose dll clock, and set the default phase */ - pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, ®_val); - reg_val &= ~(O2_SD_SEL_DLL | O2_SD_PHASE_MASK); - reg_val |= (O2_SD_SEL_DLL | O2_SD_FIX_PHASE); - pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, reg_val); + /* Update output phase */ + switch (chip->pdev->device) { + case PCI_DEVICE_ID_O2_SDS0: + case PCI_DEVICE_ID_O2_SEABIRD0: + case PCI_DEVICE_ID_O2_SEABIRD1: + case PCI_DEVICE_ID_O2_SDS1: + case PCI_DEVICE_ID_O2_FUJIN2: + /* Stop clk */ + reg_val = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + reg_val &= ~SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, reg_val, SDHCI_CLOCK_CONTROL); + + if (host->timing == MMC_TIMING_MMC_HS200 || + host->timing == MMC_TIMING_UHS_SDR104) { + /* UnLock WP */ + pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8); + scratch_8 &= 0x7f; + pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); + + /* Set pcr 0x354[16] to choose dll clock, and set the default phase */ + pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, ®_val); + reg_val &= ~(O2_SD_SEL_DLL | O2_SD_PHASE_MASK); + reg_val |= (O2_SD_SEL_DLL | O2_SD_FIX_PHASE); + pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, reg_val); + + /* Lock WP */ + pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8); + scratch_8 |= 0x80; + pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); + } - /* Lock WP */ - pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8); - scratch_8 |= 0x80; - pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); + /* Start clk */ + reg_val = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + reg_val |= SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, reg_val, SDHCI_CLOCK_CONTROL); + break; + default: + break; } - /* Start clk */ - reg_val = sdhci_readw(host, SDHCI_CLOCK_CONTROL); - reg_val |= SDHCI_CLOCK_CARD_EN; - sdhci_writew(host, reg_val, SDHCI_CLOCK_CONTROL); /* wait DLL lock, timeout value 5ms */ if (readx_poll_timeout(sdhci_o2_pll_dll_wdt_control, host, @@ -563,6 +580,7 @@ static void sdhci_pci_o2_set_clock(struct sdhci_host *host, unsigned int clock) u16 clk; u8 scratch; u32 scratch_32; + u32 dmdn_208m, dmdn_200m; struct sdhci_pci_slot *slot = sdhci_priv(host); struct sdhci_pci_chip *chip = slot->chip; @@ -578,16 +596,27 @@ static void sdhci_pci_o2_set_clock(struct sdhci_host *host, unsigned int clock) scratch &= 0x7f; pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); + if (chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9860 || + chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9861 || + chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9862 || + chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9863) { + dmdn_208m = 0x2c500000; + dmdn_200m = 0x25200000; + } else { + dmdn_208m = 0x2c280000; + dmdn_200m = 0x25100000; + } + if ((host->timing == MMC_TIMING_UHS_SDR104) && (clock == 200000000)) { pci_read_config_dword(chip->pdev, O2_SD_PLL_SETTING, &scratch_32); - if ((scratch_32 & 0xFFFF0000) != 0x2c280000) - o2_pci_set_baseclk(chip, 0x2c280000); + if ((scratch_32 & 0xFFFF0000) != dmdn_208m) + o2_pci_set_baseclk(chip, dmdn_208m); } else { pci_read_config_dword(chip->pdev, O2_SD_PLL_SETTING, &scratch_32); - if ((scratch_32 & 0xFFFF0000) != 0x25100000) - o2_pci_set_baseclk(chip, 0x25100000); + if ((scratch_32 & 0xFFFF0000) != dmdn_200m) + o2_pci_set_baseclk(chip, dmdn_200m); } pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, &scratch_32); @@ -603,6 +632,67 @@ static void sdhci_pci_o2_set_clock(struct sdhci_host *host, unsigned int clock) sdhci_o2_enable_clk(host, clk); } +static int sdhci_pci_o2_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct sdhci_host *host = mmc_priv(mmc); + struct sdhci_pci_slot *slot = sdhci_priv(host); + struct sdhci_pci_chip *chip = slot->chip; + u8 scratch8; + u16 scratch16; + int ret; + + /* Disable clock */ + sdhci_writeb(host, 0, SDHCI_CLOCK_CONTROL); + + /* Set VDD2 voltage*/ + scratch8 = sdhci_readb(host, SDHCI_POWER_CONTROL); + scratch8 &= 0x0F; + if (host->mmc->ios.timing == MMC_TIMING_SD_EXP_1_2V && + host->mmc->caps2 & MMC_CAP2_SD_EXP_1_2V) { + scratch8 |= SDHCI_VDD2_POWER_ON | SDHCI_VDD2_POWER_120; + } else { + scratch8 |= SDHCI_VDD2_POWER_ON | SDHCI_VDD2_POWER_180; + } + + sdhci_writeb(host, scratch8, SDHCI_POWER_CONTROL); + + /* UnLock WP */ + pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch8); + scratch8 &= 0x7f; + pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch8); + + /* Wait for express card clkreqn assert */ + ret = read_poll_timeout(sdhci_readb, scratch8, !(scratch8 & BIT(0)), + 1, 30000, false, host, O2_SD_EXP_INT_REG); + + if (!ret) { + /* Switch to PCIe mode */ + scratch16 = sdhci_readw(host, O2_SD_PCIE_SWITCH); + scratch16 |= BIT(8); + sdhci_writew(host, scratch16, O2_SD_PCIE_SWITCH); + } else { + /* Power off VDD2 voltage*/ + scratch8 = sdhci_readb(host, SDHCI_POWER_CONTROL); + scratch8 &= 0x0F; + sdhci_writeb(host, scratch8, SDHCI_POWER_CONTROL); + + /* Keep mode as UHSI */ + pci_read_config_word(chip->pdev, O2_SD_PARA_SET_REG1, &scratch16); + scratch16 &= ~BIT(11); + pci_write_config_word(chip->pdev, O2_SD_PARA_SET_REG1, scratch16); + + host->mmc->ios.timing = MMC_TIMING_LEGACY; + pr_info("%s: Express card initialization failed, falling back to Legacy\n", + mmc_hostname(host->mmc)); + } + /* Lock WP */ + pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch8); + scratch8 |= 0x80; + pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch8); + + return 0; +} + static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) { struct sdhci_pci_chip *chip; @@ -624,6 +714,11 @@ static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) if (caps & SDHCI_CAN_DO_8BIT) host->mmc->caps |= MMC_CAP_8_BIT_DATA; + host->quirks2 |= SDHCI_QUIRK2_BROKEN_DDR50; + + sdhci_pci_o2_enable_msi(chip, host); + + host->mmc_host_ops.execute_tuning = sdhci_o2_execute_tuning; switch (chip->pdev->device) { case PCI_DEVICE_ID_O2_SDS0: case PCI_DEVICE_ID_O2_SEABIRD0: @@ -634,10 +729,6 @@ static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) if (reg & 0x1) host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; - host->quirks2 |= SDHCI_QUIRK2_BROKEN_DDR50; - - sdhci_pci_o2_enable_msi(chip, host); - if (chip->pdev->device == PCI_DEVICE_ID_O2_SEABIRD0) { ret = pci_read_config_dword(chip->pdev, O2_SD_MISC_SETTING, ®); @@ -663,15 +754,22 @@ static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; } - host->mmc_host_ops.execute_tuning = sdhci_o2_execute_tuning; - if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2) break; /* set dll watch dog timer */ reg = sdhci_readl(host, O2_SD_VENDOR_SETTING2); reg |= (1 << 12); sdhci_writel(host, reg, O2_SD_VENDOR_SETTING2); - + break; + case PCI_DEVICE_ID_O2_GG8_9860: + case PCI_DEVICE_ID_O2_GG8_9861: + case PCI_DEVICE_ID_O2_GG8_9862: + case PCI_DEVICE_ID_O2_GG8_9863: + host->mmc->caps2 |= MMC_CAP2_NO_SDIO | MMC_CAP2_SD_EXP | MMC_CAP2_SD_EXP_1_2V; + host->mmc->caps |= MMC_CAP_HW_RESET; + host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; + slot->host->mmc_host_ops.get_cd = sdhci_o2_get_cd; + host->mmc_host_ops.init_sd_express = sdhci_pci_o2_init_sd_express; break; default: break; @@ -684,6 +782,7 @@ static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip) { int ret; u8 scratch; + u16 scratch16; u32 scratch_32; switch (chip->pdev->device) { @@ -893,6 +992,46 @@ static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip) scratch |= 0x80; pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); break; + case PCI_DEVICE_ID_O2_GG8_9860: + case PCI_DEVICE_ID_O2_GG8_9861: + case PCI_DEVICE_ID_O2_GG8_9862: + case PCI_DEVICE_ID_O2_GG8_9863: + /* UnLock WP */ + ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch); + if (ret) + return ret; + scratch &= 0x7f; + pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); + + /* Select mode switch source as software control */ + pci_read_config_word(chip->pdev, O2_SD_PARA_SET_REG1, &scratch16); + scratch16 &= 0xF8FF; + scratch16 |= BIT(9); + pci_write_config_word(chip->pdev, O2_SD_PARA_SET_REG1, scratch16); + + /* set VDD1 supply source */ + pci_read_config_word(chip->pdev, O2_SD_VDDX_CTRL_REG, &scratch16); + scratch16 &= 0xFFE3; + scratch16 |= BIT(3); + pci_write_config_word(chip->pdev, O2_SD_VDDX_CTRL_REG, scratch16); + + /* Set host drive strength*/ + scratch16 = 0x0025; + pci_write_config_word(chip->pdev, O2_SD_PLL_SETTING, scratch16); + + /* Set output delay*/ + pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, &scratch_32); + scratch_32 &= 0xFF0FFF00; + scratch_32 |= 0x00B0003B; + pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, scratch_32); + + /* Lock WP */ + ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch); + if (ret) + return ret; + scratch |= 0x80; + pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); + break; } return 0; diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h index 9c8863956381..153704f812ed 100644 --- a/drivers/mmc/host/sdhci-pci.h +++ b/drivers/mmc/host/sdhci-pci.h @@ -11,6 +11,10 @@ #define PCI_DEVICE_ID_O2_FUJIN2 0x8520 #define PCI_DEVICE_ID_O2_SEABIRD0 0x8620 #define PCI_DEVICE_ID_O2_SEABIRD1 0x8621 +#define PCI_DEVICE_ID_O2_GG8_9860 0x9860 +#define PCI_DEVICE_ID_O2_GG8_9861 0x9861 +#define PCI_DEVICE_ID_O2_GG8_9862 0x9862 +#define PCI_DEVICE_ID_O2_GG8_9863 0x9863 #define PCI_DEVICE_ID_INTEL_PCH_SDIO0 0x8809 #define PCI_DEVICE_ID_INTEL_PCH_SDIO1 0x880a diff --git a/drivers/mmc/host/sdhci-pic32.c b/drivers/mmc/host/sdhci-pic32.c index 6696b6bdd88e..7a0351a9c74e 100644 --- a/drivers/mmc/host/sdhci-pic32.c +++ b/drivers/mmc/host/sdhci-pic32.c @@ -210,7 +210,7 @@ err: return ret; } -static int pic32_sdhci_remove(struct platform_device *pdev) +static void pic32_sdhci_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct pic32_sdhci_priv *sdhci_pdata = sdhci_priv(host); @@ -221,8 +221,6 @@ static int pic32_sdhci_remove(struct platform_device *pdev) clk_disable_unprepare(sdhci_pdata->base_clk); clk_disable_unprepare(sdhci_pdata->sys_clk); sdhci_pltfm_free(pdev); - - return 0; } static const struct of_device_id pic32_sdhci_id_table[] = { @@ -238,7 +236,7 @@ static struct platform_driver pic32_sdhci_driver = { .of_match_table = of_match_ptr(pic32_sdhci_id_table), }, .probe = pic32_sdhci_probe, - .remove = pic32_sdhci_remove, + .remove_new = pic32_sdhci_remove, }; module_platform_driver(pic32_sdhci_driver); diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index 673e750a8490..a72e123a585d 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c @@ -166,9 +166,9 @@ void sdhci_pltfm_free(struct platform_device *pdev) } EXPORT_SYMBOL_GPL(sdhci_pltfm_free); -int sdhci_pltfm_register(struct platform_device *pdev, - const struct sdhci_pltfm_data *pdata, - size_t priv_size) +int sdhci_pltfm_init_and_add_host(struct platform_device *pdev, + const struct sdhci_pltfm_data *pdata, + size_t priv_size) { struct sdhci_host *host; int ret = 0; @@ -185,21 +185,17 @@ int sdhci_pltfm_register(struct platform_device *pdev, return ret; } -EXPORT_SYMBOL_GPL(sdhci_pltfm_register); +EXPORT_SYMBOL_GPL(sdhci_pltfm_init_and_add_host); -int sdhci_pltfm_unregister(struct platform_device *pdev) +void sdhci_pltfm_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); - struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); sdhci_remove_host(host, dead); - clk_disable_unprepare(pltfm_host->clk); sdhci_pltfm_free(pdev); - - return 0; } -EXPORT_SYMBOL_GPL(sdhci_pltfm_unregister); +EXPORT_SYMBOL_GPL(sdhci_pltfm_remove); #ifdef CONFIG_PM_SLEEP int sdhci_pltfm_suspend(struct device *dev) diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h index 9bd717ff784b..b81d5b0fd616 100644 --- a/drivers/mmc/host/sdhci-pltfm.h +++ b/drivers/mmc/host/sdhci-pltfm.h @@ -99,10 +99,10 @@ extern struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, size_t priv_size); extern void sdhci_pltfm_free(struct platform_device *pdev); -extern int sdhci_pltfm_register(struct platform_device *pdev, - const struct sdhci_pltfm_data *pdata, - size_t priv_size); -extern int sdhci_pltfm_unregister(struct platform_device *pdev); +extern int sdhci_pltfm_init_and_add_host(struct platform_device *pdev, + const struct sdhci_pltfm_data *pdata, + size_t priv_size); +extern void sdhci_pltfm_remove(struct platform_device *pdev); extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host); diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c index 91aca8f8d6ef..b75cbea88b40 100644 --- a/drivers/mmc/host/sdhci-pxav2.c +++ b/drivers/mmc/host/sdhci-pxav2.c @@ -19,7 +19,6 @@ #include <linux/platform_data/pxa_sdhci.h> #include <linux/slab.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/mmc/sdio.h> #include <linux/mmc/mmc.h> #include <linux/pinctrl/consumer.h> @@ -269,26 +268,21 @@ static int sdhci_pxav2_probe(struct platform_device *pdev) pltfm_host = sdhci_priv(host); pxav2_host = sdhci_pltfm_priv(pltfm_host); - clk = devm_clk_get(dev, "io"); - if (IS_ERR(clk) && PTR_ERR(clk) != -EPROBE_DEFER) - clk = devm_clk_get(dev, NULL); + clk = devm_clk_get_optional_enabled(dev, "io"); + if (!clk) + clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err_probe(dev, ret, "failed to get io clock\n"); goto free; } pltfm_host->clk = clk; - ret = clk_prepare_enable(clk); - if (ret) { - dev_err(dev, "failed to enable io clock\n"); - goto free; - } clk_core = devm_clk_get_optional_enabled(dev, "core"); if (IS_ERR(clk_core)) { ret = PTR_ERR(clk_core); dev_err_probe(dev, ret, "failed to enable core clock\n"); - goto disable_clk; + goto free; } host->quirks = SDHCI_QUIRK_BROKEN_ADMA @@ -340,12 +334,10 @@ static int sdhci_pxav2_probe(struct platform_device *pdev) ret = sdhci_add_host(host); if (ret) - goto disable_clk; + goto free; return 0; -disable_clk: - clk_disable_unprepare(clk); free: sdhci_pltfm_free(pdev); return ret; @@ -359,7 +351,7 @@ static struct platform_driver sdhci_pxav2_driver = { .pm = &sdhci_pltfm_pmops, }, .probe = sdhci_pxav2_probe, - .remove = sdhci_pltfm_unregister, + .remove_new = sdhci_pltfm_remove, }; module_platform_driver(sdhci_pxav2_driver); diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index e39dcc998772..3af43ac05825 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -470,7 +470,7 @@ err_clk_get: return ret; } -static int sdhci_pxav3_remove(struct platform_device *pdev) +static void sdhci_pxav3_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -486,8 +486,6 @@ static int sdhci_pxav3_remove(struct platform_device *pdev) clk_disable_unprepare(pxa->clk_core); sdhci_pltfm_free(pdev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -570,7 +568,7 @@ static struct platform_driver sdhci_pxav3_driver = { .pm = &sdhci_pxav3_pmops, }, .probe = sdhci_pxav3_probe, - .remove = sdhci_pxav3_remove, + .remove_new = sdhci_pxav3_remove, }; module_platform_driver(sdhci_pxav3_driver); diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 504015e84308..0e8a8ac14e56 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -20,7 +20,6 @@ #include <linux/gpio.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_gpio.h> #include <linux/pm.h> #include <linux/pm_runtime.h> @@ -668,7 +667,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev) return ret; } -static int sdhci_s3c_remove(struct platform_device *pdev) +static void sdhci_s3c_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_s3c *sc = sdhci_priv(host); @@ -688,8 +687,6 @@ static int sdhci_s3c_remove(struct platform_device *pdev) clk_disable_unprepare(sc->clk_io); sdhci_free_host(host); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -776,7 +773,7 @@ MODULE_DEVICE_TABLE(of, sdhci_s3c_dt_match); static struct platform_driver sdhci_s3c_driver = { .probe = sdhci_s3c_probe, - .remove = sdhci_s3c_remove, + .remove_new = sdhci_s3c_remove, .id_table = sdhci_s3c_driver_ids, .driver = { .name = "s3c-sdhci", diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c index c79035727b20..c81bdfa97b89 100644 --- a/drivers/mmc/host/sdhci-spear.c +++ b/drivers/mmc/host/sdhci-spear.c @@ -117,7 +117,7 @@ err: return ret; } -static int sdhci_remove(struct platform_device *pdev) +static void sdhci_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct spear_sdhci *sdhci = sdhci_priv(host); @@ -131,8 +131,6 @@ static int sdhci_remove(struct platform_device *pdev) sdhci_remove_host(host, dead); clk_disable_unprepare(sdhci->clk); sdhci_free_host(host); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -170,23 +168,21 @@ static int sdhci_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(sdhci_pm_ops, sdhci_suspend, sdhci_resume); -#ifdef CONFIG_OF static const struct of_device_id sdhci_spear_id_table[] = { { .compatible = "st,spear300-sdhci" }, {} }; MODULE_DEVICE_TABLE(of, sdhci_spear_id_table); -#endif static struct platform_driver sdhci_driver = { .driver = { .name = "sdhci", .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &sdhci_pm_ops, - .of_match_table = of_match_ptr(sdhci_spear_id_table), + .of_match_table = sdhci_spear_id_table, }, .probe = sdhci_probe, - .remove = sdhci_remove, + .remove_new = sdhci_remove, }; module_platform_driver(sdhci_driver); diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index 7f4ee2e12735..649ae075e229 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -9,9 +9,10 @@ #include <linux/dma-mapping.h> #include <linux/highmem.h> #include <linux/iopoll.h> +#include <linux/mmc/host.h> +#include <linux/mmc/mmc.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_gpio.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> @@ -73,6 +74,11 @@ #define SDHCI_SPRD_CLK_DEF_RATE 26000000 #define SDHCI_SPRD_PHY_DLL_CLK 52000000 +#define SDHCI_SPRD_MAX_RANGE 0xff +#define SDHCI_SPRD_CMD_DLY_MASK GENMASK(15, 8) +#define SDHCI_SPRD_POSRD_DLY_MASK GENMASK(23, 16) +#define SDHCI_SPRD_CPST_EN GENMASK(27, 24) + struct sdhci_sprd_host { u32 version; struct clk *clk_sdio; @@ -86,6 +92,11 @@ struct sdhci_sprd_host { u32 phy_delay[MMC_TIMING_MMC_HS400 + 2]; }; +enum sdhci_sprd_tuning_type { + SDHCI_SPRD_TUNING_SD_HS_CMD, + SDHCI_SPRD_TUNING_SD_HS_DATA, +}; + struct sdhci_sprd_phy_cfg { const char *property; u8 timing; @@ -533,6 +544,138 @@ static void sdhci_sprd_hs400_enhanced_strobe(struct mmc_host *mmc, SDHCI_SPRD_REG_32_DLL_DLY); } +static int mmc_send_tuning_cmd(struct mmc_card *card) +{ + return mmc_send_status(card, NULL); +} + +static int mmc_send_tuning_data(struct mmc_card *card) +{ + u8 *status; + int ret; + + status = kmalloc(64, GFP_KERNEL); + if (!status) + return -ENOMEM; + + ret = mmc_sd_switch(card, 0, 0, 0, status); + + kfree(status); + + return ret; +} + +static int sdhci_sprd_get_best_clk_sample(struct mmc_host *mmc, u8 *value) +{ + int range_end = SDHCI_SPRD_MAX_RANGE; + int range_length = 0; + int middle_range = 0; + int count = 0; + int i; + + for (i = 0; i <= SDHCI_SPRD_MAX_RANGE; i++) { + if (value[i]) { + pr_debug("%s: tuning ok: %d\n", mmc_hostname(mmc), i); + count++; + } else { + pr_debug("%s: tuning fail: %d\n", mmc_hostname(mmc), i); + if (range_length < count) { + range_length = count; + range_end = i - 1; + count = 0; + } + } + } + + if (!count) + return -EIO; + + if (count > range_length) { + range_length = count; + range_end = i - 1; + } + + middle_range = range_end - (range_length - 1) / 2; + + return middle_range; +} + +static int sdhci_sprd_tuning(struct mmc_host *mmc, struct mmc_card *card, + enum sdhci_sprd_tuning_type type) +{ + struct sdhci_host *host = mmc_priv(mmc); + struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host); + u32 *p = sprd_host->phy_delay; + u32 dll_cfg, dll_dly; + int best_clk_sample; + int err = 0; + u8 *value; + int i; + + value = kmalloc(SDHCI_SPRD_MAX_RANGE + 1, GFP_KERNEL); + if (!value) + return -ENOMEM; + + sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + + dll_cfg = sdhci_readl(host, SDHCI_SPRD_REG_32_DLL_CFG); + dll_cfg &= ~SDHCI_SPRD_CPST_EN; + sdhci_writel(host, dll_cfg, SDHCI_SPRD_REG_32_DLL_CFG); + + dll_dly = p[mmc->ios.timing]; + + for (i = 0; i <= SDHCI_SPRD_MAX_RANGE; i++) { + if (type == SDHCI_SPRD_TUNING_SD_HS_CMD) { + dll_dly &= ~SDHCI_SPRD_CMD_DLY_MASK; + dll_dly |= ((i << 8) & SDHCI_SPRD_CMD_DLY_MASK); + } else { + dll_dly &= ~SDHCI_SPRD_POSRD_DLY_MASK; + dll_dly |= ((i << 16) & SDHCI_SPRD_POSRD_DLY_MASK); + } + + sdhci_writel(host, dll_dly, SDHCI_SPRD_REG_32_DLL_DLY); + + if (type == SDHCI_SPRD_TUNING_SD_HS_CMD) + value[i] = !mmc_send_tuning_cmd(card); + else + value[i] = !mmc_send_tuning_data(card); + } + + best_clk_sample = sdhci_sprd_get_best_clk_sample(mmc, value); + if (best_clk_sample < 0) { + dev_err(mmc_dev(host->mmc), "all tuning phase fail!\n"); + goto out; + } + + if (type == SDHCI_SPRD_TUNING_SD_HS_CMD) { + p[mmc->ios.timing] &= ~SDHCI_SPRD_CMD_DLY_MASK; + p[mmc->ios.timing] |= ((best_clk_sample << 8) & SDHCI_SPRD_CMD_DLY_MASK); + } else { + p[mmc->ios.timing] &= ~(SDHCI_SPRD_POSRD_DLY_MASK); + p[mmc->ios.timing] |= ((best_clk_sample << 16) & SDHCI_SPRD_POSRD_DLY_MASK); + } + + pr_debug("%s: the best clk sample %d, delay value 0x%08x\n", + mmc_hostname(host->mmc), best_clk_sample, p[mmc->ios.timing]); + +out: + sdhci_writel(host, p[mmc->ios.timing], SDHCI_SPRD_REG_32_DLL_DLY); + + kfree(value); + + return err; +} + +static int sdhci_sprd_prepare_sd_hs_cmd_tuning(struct mmc_host *mmc, struct mmc_card *card) +{ + return sdhci_sprd_tuning(mmc, card, SDHCI_SPRD_TUNING_SD_HS_CMD); +} + +static int sdhci_sprd_execute_sd_hs_data_tuning(struct mmc_host *mmc, struct mmc_card *card) +{ + return sdhci_sprd_tuning(mmc, card, SDHCI_SPRD_TUNING_SD_HS_DATA); +} + static void sdhci_sprd_phy_param_parse(struct sdhci_sprd_host *sprd_host, struct device_node *np) { @@ -577,6 +720,11 @@ 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; + host->mmc_host_ops.prepare_sd_hs_tuning = + sdhci_sprd_prepare_sd_hs_cmd_tuning; + host->mmc_host_ops.execute_sd_hs_tuning = + sdhci_sprd_execute_sd_hs_data_tuning; + /* * We can not use the standard ops to change and detect the voltage * signal for Spreadtrum SD host controller, since our voltage regulator @@ -720,7 +868,7 @@ pltfm_free: return ret; } -static int sdhci_sprd_remove(struct platform_device *pdev) +static void sdhci_sprd_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host); @@ -732,8 +880,6 @@ static int sdhci_sprd_remove(struct platform_device *pdev) clk_disable_unprepare(sprd_host->clk_2x_enable); sdhci_pltfm_free(pdev); - - return 0; } static const struct of_device_id sdhci_sprd_of_match[] = { @@ -800,7 +946,7 @@ static const struct dev_pm_ops sdhci_sprd_pm_ops = { static struct platform_driver sdhci_sprd_driver = { .probe = sdhci_sprd_probe, - .remove = sdhci_sprd_remove, + .remove_new = sdhci_sprd_remove, .driver = { .name = "sdhci_sprd_r11", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index 6415916fbd91..d12532b96b51 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c @@ -348,7 +348,6 @@ static int sdhci_st_probe(struct platform_device *pdev) struct clk *clk, *icnclk; int ret = 0; u16 host_version; - struct resource *res; struct reset_control *rstc; clk = devm_clk_get(&pdev->dev, "mmc"); @@ -397,9 +396,7 @@ static int sdhci_st_probe(struct platform_device *pdev) } /* Configure the FlashSS Top registers for setting eMMC TX/RX delay */ - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "top-mmc-delay"); - pdata->top_ioaddr = devm_ioremap_resource(&pdev->dev, res); + pdata->top_ioaddr = devm_platform_ioremap_resource_byname(pdev, "top-mmc-delay"); if (IS_ERR(pdata->top_ioaddr)) pdata->top_ioaddr = NULL; @@ -434,20 +431,20 @@ err_pltfm_init: return ret; } -static int sdhci_st_remove(struct platform_device *pdev) +static void sdhci_st_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host); struct reset_control *rstc = pdata->rstc; + struct clk *clk = pltfm_host->clk; - sdhci_pltfm_unregister(pdev); + sdhci_pltfm_remove(pdev); clk_disable_unprepare(pdata->icnclk); + clk_disable_unprepare(clk); reset_control_assert(rstc); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -510,7 +507,7 @@ MODULE_DEVICE_TABLE(of, st_sdhci_match); static struct platform_driver sdhci_st_driver = { .probe = sdhci_st_probe, - .remove = sdhci_st_remove, + .remove_new = sdhci_st_remove, .driver = { .name = "sdhci-st", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index bff084f178c9..1ad0a6b3a2eb 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -19,7 +19,6 @@ #include <linux/mmc/mmc.h> #include <linux/mmc/slot-gpio.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/of.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> @@ -1818,7 +1817,7 @@ err_parse_dt: return rc; } -static int sdhci_tegra_remove(struct platform_device *pdev) +static void sdhci_tegra_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -1834,8 +1833,6 @@ static int sdhci_tegra_remove(struct platform_device *pdev) clk_disable_unprepare(tegra_host->tmclk); sdhci_pltfm_free(pdev); - - return 0; } static int __maybe_unused sdhci_tegra_runtime_suspend(struct device *dev) @@ -1933,7 +1930,7 @@ static struct platform_driver sdhci_tegra_driver = { .pm = &sdhci_tegra_dev_pm_ops, }, .probe = sdhci_tegra_probe, - .remove = sdhci_tegra_remove, + .remove_new = sdhci_tegra_remove, }; module_platform_driver(sdhci_tegra_driver); diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c index 08e838400b52..25ba7aecc3be 100644 --- a/drivers/mmc/host/sdhci-xenon.c +++ b/drivers/mmc/host/sdhci-xenon.c @@ -578,7 +578,7 @@ free_pltfm: return err; } -static int xenon_remove(struct platform_device *pdev) +static void xenon_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -595,8 +595,6 @@ static int xenon_remove(struct platform_device *pdev) clk_disable_unprepare(pltfm_host->clk); sdhci_pltfm_free(pdev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -705,7 +703,7 @@ static struct platform_driver sdhci_xenon_driver = { .pm = &sdhci_xenon_dev_pm_ops, }, .probe = xenon_probe, - .remove = xenon_remove, + .remove_new = xenon_remove, }; module_platform_driver(sdhci_xenon_driver); diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index 7cdf0f54e3a5..c125485ba80e 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -866,22 +866,22 @@ err_pltfm_free: return ret; } -static int sdhci_am654_remove(struct platform_device *pdev) +static void sdhci_am654_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct device *dev = &pdev->dev; int ret; - ret = pm_runtime_resume_and_get(&pdev->dev); + ret = pm_runtime_get_sync(dev); if (ret < 0) - return ret; + dev_err(dev, "pm_runtime_get_sync() Failed\n"); sdhci_remove_host(host, true); clk_disable_unprepare(pltfm_host->clk); - pm_runtime_disable(&pdev->dev); - pm_runtime_put_noidle(&pdev->dev); + pm_runtime_disable(dev); + pm_runtime_put_noidle(dev); sdhci_pltfm_free(pdev); - return 0; } #ifdef CONFIG_PM @@ -993,7 +993,7 @@ static struct platform_driver sdhci_am654_driver = { .of_match_table = sdhci_am654_of_match, }, .probe = sdhci_am654_probe, - .remove = sdhci_am654_remove, + .remove_new = sdhci_am654_remove, }; module_platform_driver(sdhci_am654_driver); diff --git a/drivers/mmc/host/sdhci_f_sdh30.c b/drivers/mmc/host/sdhci_f_sdh30.c index a202a69a4b08..c58e7cb1e2a7 100644 --- a/drivers/mmc/host/sdhci_f_sdh30.c +++ b/drivers/mmc/host/sdhci_f_sdh30.c @@ -29,9 +29,16 @@ struct f_sdhost_priv { bool enable_cmd_dat_delay; }; +static void *sdhci_f_sdhost_priv(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + + return sdhci_pltfm_priv(pltfm_host); +} + static void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host) { - struct f_sdhost_priv *priv = sdhci_priv(host); + struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host); u32 ctrl = 0; usleep_range(2500, 3000); @@ -64,7 +71,7 @@ static unsigned int sdhci_f_sdh30_get_min_clock(struct sdhci_host *host) static void sdhci_f_sdh30_reset(struct sdhci_host *host, u8 mask) { - struct f_sdhost_priv *priv = sdhci_priv(host); + struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host); u32 ctl; if (sdhci_readw(host, SDHCI_CLOCK_CONTROL) == 0) @@ -95,30 +102,32 @@ static const struct sdhci_ops sdhci_f_sdh30_ops = { .set_uhs_signaling = sdhci_set_uhs_signaling, }; +static const struct sdhci_pltfm_data sdhci_f_sdh30_pltfm_data = { + .ops = &sdhci_f_sdh30_ops, + .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC + | SDHCI_QUIRK_INVERTED_WRITE_PROTECT, + .quirks2 = SDHCI_QUIRK2_SUPPORT_SINGLE + | SDHCI_QUIRK2_TUNING_WORK_AROUND, +}; + static int sdhci_f_sdh30_probe(struct platform_device *pdev) { struct sdhci_host *host; struct device *dev = &pdev->dev; - int irq, ctrl = 0, ret = 0; + int ctrl = 0, ret = 0; struct f_sdhost_priv *priv; + struct sdhci_pltfm_host *pltfm_host; u32 reg = 0; - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; - - host = sdhci_alloc_host(dev, sizeof(struct f_sdhost_priv)); + host = sdhci_pltfm_init(pdev, &sdhci_f_sdh30_pltfm_data, + sizeof(struct f_sdhost_priv)); if (IS_ERR(host)) return PTR_ERR(host); - priv = sdhci_priv(host); + pltfm_host = sdhci_priv(host); + priv = sdhci_pltfm_priv(pltfm_host); priv->dev = dev; - host->quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | - SDHCI_QUIRK_INVERTED_WRITE_PROTECT; - host->quirks2 = SDHCI_QUIRK2_SUPPORT_SINGLE | - SDHCI_QUIRK2_TUNING_WORK_AROUND; - priv->enable_cmd_dat_delay = device_property_read_bool(dev, "fujitsu,cmd-dat-delay-select"); @@ -126,18 +135,6 @@ static int sdhci_f_sdh30_probe(struct platform_device *pdev) if (ret) goto err; - platform_set_drvdata(pdev, host); - - host->hw_name = "f_sdh30"; - host->ops = &sdhci_f_sdh30_ops; - host->irq = irq; - - host->ioaddr = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(host->ioaddr)) { - ret = PTR_ERR(host->ioaddr); - goto err; - } - if (dev_of_node(dev)) { sdhci_get_of_property(pdev); @@ -204,26 +201,24 @@ err_rst: err_clk: clk_disable_unprepare(priv->clk_iface); err: - sdhci_free_host(host); + sdhci_pltfm_free(pdev); + return ret; } -static int sdhci_f_sdh30_remove(struct platform_device *pdev) +static void sdhci_f_sdh30_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); - struct f_sdhost_priv *priv = sdhci_priv(host); - - sdhci_remove_host(host, readl(host->ioaddr + SDHCI_INT_STATUS) == - 0xffffffff); + struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host); + struct clk *clk_iface = priv->clk_iface; + struct reset_control *rst = priv->rst; + struct clk *clk = priv->clk; - reset_control_assert(priv->rst); - clk_disable_unprepare(priv->clk); - clk_disable_unprepare(priv->clk_iface); + sdhci_pltfm_remove(pdev); - sdhci_free_host(host); - platform_set_drvdata(pdev, NULL); - - return 0; + reset_control_assert(rst); + clk_disable_unprepare(clk); + clk_disable_unprepare(clk_iface); } #ifdef CONFIG_OF @@ -251,8 +246,8 @@ static struct platform_driver sdhci_f_sdh30_driver = { .acpi_match_table = ACPI_PTR(f_sdh30_acpi_ids), .pm = &sdhci_pltfm_pmops, }, - .probe = sdhci_f_sdh30_probe, - .remove = sdhci_f_sdh30_remove, + .probe = sdhci_f_sdh30_probe, + .remove_new = sdhci_f_sdh30_remove, }; module_platform_driver(sdhci_f_sdh30_driver); diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 5cf53348372a..077d711e964e 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -46,7 +46,6 @@ #include <linux/mmc/slot-gpio.h> #include <linux/mod_devicetable.h> #include <linux/mutex.h> -#include <linux/of_device.h> #include <linux/pagemap.h> #include <linux/platform_data/sh_mmcif.h> #include <linux/platform_device.h> @@ -1509,7 +1508,7 @@ err_host: return ret; } -static int sh_mmcif_remove(struct platform_device *pdev) +static void sh_mmcif_remove(struct platform_device *pdev) { struct sh_mmcif_host *host = platform_get_drvdata(pdev); @@ -1533,8 +1532,6 @@ static int sh_mmcif_remove(struct platform_device *pdev) mmc_free_host(host->mmc); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1561,7 +1558,7 @@ static const struct dev_pm_ops sh_mmcif_dev_pm_ops = { static struct platform_driver sh_mmcif_driver = { .probe = sh_mmcif_probe, - .remove = sh_mmcif_remove, + .remove_new = sh_mmcif_remove, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/sunplus-mmc.c b/drivers/mmc/host/sunplus-mmc.c index db5e0dcdfa7f..13c7cc0b6180 100644 --- a/drivers/mmc/host/sunplus-mmc.c +++ b/drivers/mmc/host/sunplus-mmc.c @@ -863,11 +863,9 @@ static int spmmc_drv_probe(struct platform_device *pdev) struct spmmc_host *host; int ret = 0; - mmc = mmc_alloc_host(sizeof(*host), &pdev->dev); - if (!mmc) { - ret = -ENOMEM; - goto probe_free_host; - } + mmc = devm_mmc_alloc_host(&pdev->dev, sizeof(struct spmmc_host)); + if (!mmc) + return -ENOMEM; host = mmc_priv(mmc); host->mmc = mmc; @@ -887,7 +885,7 @@ static int spmmc_drv_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, PTR_ERR(host->rstc), "rst get fail\n"); host->irq = platform_get_irq(pdev, 0); - if (host->irq <= 0) + if (host->irq < 0) return host->irq; ret = devm_request_threaded_irq(&pdev->dev, host->irq, @@ -902,7 +900,7 @@ static int spmmc_drv_probe(struct platform_device *pdev) ret = mmc_of_parse(mmc); if (ret) - goto probe_free_host; + goto clk_disable; mmc->ops = &spmmc_ops; mmc->f_min = SPMMC_MIN_CLK; @@ -911,7 +909,7 @@ static int spmmc_drv_probe(struct platform_device *pdev) ret = mmc_regulator_get_supply(mmc); if (ret) - goto probe_free_host; + goto clk_disable; if (!mmc->ocr_avail) mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; @@ -927,18 +925,21 @@ static int spmmc_drv_probe(struct platform_device *pdev) host->tuning_info.enable_tuning = 1; pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); - mmc_add_host(mmc); + ret = mmc_add_host(mmc); + if (ret) + goto pm_disable; - return ret; + return 0; -probe_free_host: - if (mmc) - mmc_free_host(mmc); +pm_disable: + pm_runtime_disable(&pdev->dev); +clk_disable: + clk_disable_unprepare(host->clk); return ret; } -static int spmmc_drv_remove(struct platform_device *dev) +static void spmmc_drv_remove(struct platform_device *dev) { struct spmmc_host *host = platform_get_drvdata(dev); @@ -947,10 +948,6 @@ static int spmmc_drv_remove(struct platform_device *dev) clk_disable_unprepare(host->clk); pm_runtime_put_noidle(&dev->dev); pm_runtime_disable(&dev->dev); - platform_set_drvdata(dev, NULL); - mmc_free_host(host->mmc); - - return 0; } static int spmmc_pm_runtime_suspend(struct device *dev) @@ -985,7 +982,7 @@ MODULE_DEVICE_TABLE(of, spmmc_of_table); static struct platform_driver spmmc_driver = { .probe = spmmc_drv_probe, - .remove = spmmc_drv_remove, + .remove_new = spmmc_drv_remove, .driver = { .name = "spmmc", .pm = pm_ptr(&spmmc_pm_ops), diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index 69dcb8805e05..d3bd0ac99ec4 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -1486,7 +1486,7 @@ error_free_host: return ret; } -static int sunxi_mmc_remove(struct platform_device *pdev) +static void sunxi_mmc_remove(struct platform_device *pdev) { struct mmc_host *mmc = platform_get_drvdata(pdev); struct sunxi_mmc_host *host = mmc_priv(mmc); @@ -1499,8 +1499,6 @@ static int sunxi_mmc_remove(struct platform_device *pdev) } dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); mmc_free_host(mmc); - - return 0; } #ifdef CONFIG_PM @@ -1556,7 +1554,7 @@ static struct platform_driver sunxi_mmc_driver = { .pm = &sunxi_mmc_pm_ops, }, .probe = sunxi_mmc_probe, - .remove = sunxi_mmc_remove, + .remove_new = sunxi_mmc_remove, }; module_platform_driver(sunxi_mmc_driver); diff --git a/drivers/mmc/host/uniphier-sd.c b/drivers/mmc/host/uniphier-sd.c index 61acd69fac0e..1404989e6151 100644 --- a/drivers/mmc/host/uniphier-sd.c +++ b/drivers/mmc/host/uniphier-sd.c @@ -13,7 +13,6 @@ #include <linux/mmc/host.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> #include <linux/regmap.h> @@ -706,19 +705,19 @@ static int uniphier_sd_probe(struct platform_device *pdev) tmio_data->max_segs = 1; tmio_data->max_blk_count = U16_MAX; - ret = tmio_mmc_host_probe(host); - if (ret) - goto disable_clk; + sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, TMIO_MASK_ALL); ret = devm_request_irq(dev, irq, tmio_mmc_irq, IRQF_SHARED, dev_name(dev), host); if (ret) - goto remove_host; + goto disable_clk; + + ret = tmio_mmc_host_probe(host); + if (ret) + goto disable_clk; return 0; -remove_host: - tmio_mmc_host_remove(host); disable_clk: uniphier_sd_clk_disable(host); free_host: @@ -727,15 +726,13 @@ free_host: return ret; } -static int uniphier_sd_remove(struct platform_device *pdev) +static void uniphier_sd_remove(struct platform_device *pdev) { struct tmio_mmc_host *host = platform_get_drvdata(pdev); tmio_mmc_host_remove(host); uniphier_sd_clk_disable(host); tmio_mmc_host_free(host); - - return 0; } static const struct of_device_id uniphier_sd_match[] = { @@ -757,7 +754,7 @@ MODULE_DEVICE_TABLE(of, uniphier_sd_match); static struct platform_driver uniphier_sd_driver = { .probe = uniphier_sd_probe, - .remove = uniphier_sd_remove, + .remove_new = uniphier_sd_remove, .driver = { .name = "uniphier-sd", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c index 2e17903658fc..6e421445d56c 100644 --- a/drivers/mmc/host/usdhi6rol0.c +++ b/drivers/mmc/host/usdhi6rol0.c @@ -1884,7 +1884,7 @@ e_free_mmc: return ret; } -static int usdhi6_remove(struct platform_device *pdev) +static void usdhi6_remove(struct platform_device *pdev) { struct usdhi6_host *host = platform_get_drvdata(pdev); @@ -1895,13 +1895,11 @@ static int usdhi6_remove(struct platform_device *pdev) usdhi6_dma_release(host); clk_disable_unprepare(host->clk); mmc_free_host(host->mmc); - - return 0; } static struct platform_driver usdhi6_driver = { .probe = usdhi6_probe, - .remove = usdhi6_remove, + .remove_new = usdhi6_remove, .driver = { .name = "usdhi6rol0", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index a2b0d9461665..ba6044b16e07 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c @@ -1160,7 +1160,6 @@ static int via_sd_probe(struct pci_dev *pcidev, unmap: iounmap(sdhost->mmiobase); free_mmc_host: - dev_set_drvdata(&pcidev->dev, NULL); mmc_free_host(mmc); release: pci_release_regions(pcidev); @@ -1212,7 +1211,6 @@ static void via_sd_remove(struct pci_dev *pcidev) writeb(gatt, sdhost->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT); iounmap(sdhost->mmiobase); - dev_set_drvdata(&pcidev->dev, NULL); mmc_free_host(sdhost->mmc); pci_release_regions(pcidev); pci_disable_device(pcidev); diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c index 521af9251f33..001a468bc149 100644 --- a/drivers/mmc/host/wbsd.c +++ b/drivers/mmc/host/wbsd.c @@ -1264,8 +1264,6 @@ static void wbsd_free_mmc(struct device *dev) del_timer_sync(&host->ignore_timer); mmc_free_host(mmc); - - dev_set_drvdata(dev, NULL); } /* @@ -1705,8 +1703,6 @@ static int wbsd_init(struct device *dev, int base, int irq, int dma, wbsd_release_resources(host); wbsd_free_mmc(dev); - - mmc_free_host(mmc); return ret; } @@ -1758,11 +1754,9 @@ static int wbsd_probe(struct platform_device *dev) return wbsd_init(&dev->dev, param_io, param_irq, param_dma, 0); } -static int wbsd_remove(struct platform_device *dev) +static void wbsd_remove(struct platform_device *dev) { wbsd_shutdown(&dev->dev, 0); - - return 0; } /* @@ -1904,8 +1898,7 @@ static struct platform_device *wbsd_device; static struct platform_driver wbsd_driver = { .probe = wbsd_probe, - .remove = wbsd_remove, - + .remove_new = wbsd_remove, .suspend = wbsd_platform_suspend, .resume = wbsd_platform_resume, .driver = { diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c index 68525d900046..77d5f1d24489 100644 --- a/drivers/mmc/host/wmt-sdmmc.c +++ b/drivers/mmc/host/wmt-sdmmc.c @@ -21,7 +21,6 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> -#include <linux/of_device.h> #include <linux/mmc/host.h> #include <linux/mmc/mmc.h> @@ -880,7 +879,7 @@ fail1: return ret; } -static int wmt_mci_remove(struct platform_device *pdev) +static void wmt_mci_remove(struct platform_device *pdev) { struct mmc_host *mmc; struct wmt_mci_priv *priv; @@ -918,8 +917,6 @@ static int wmt_mci_remove(struct platform_device *pdev) mmc_free_host(mmc); dev_info(&pdev->dev, "WMT MCI device removed\n"); - - return 0; } #ifdef CONFIG_PM @@ -989,7 +986,7 @@ static const struct dev_pm_ops wmt_mci_pm = { static struct platform_driver wmt_mci_driver = { .probe = wmt_mci_probe, - .remove = wmt_mci_remove, + .remove_new = wmt_mci_remove, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, |