[PATCH v2 3/7] mmc: tegra: use devm help functions to get the clk and gpio
Simplify the error and remove path. Signed-off-by: Kevin Hao --- v2: No change. drivers/mmc/host/sdhci-tegra.c | 13 +++-- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index f3778d58d1cd..0643f66b4e14 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -286,7 +286,8 @@ static int sdhci_tegra_probe(struct platform_device *pdev) goto err_parse_dt; if (gpio_is_valid(tegra_host->power_gpio)) { - rc = gpio_request(tegra_host->power_gpio, "sdhci_power"); + rc = devm_gpio_request(&pdev->dev, tegra_host->power_gpio, + "sdhci_power"); if (rc) { dev_err(mmc_dev(host->mmc), "failed to allocate power gpio\n"); @@ -295,7 +296,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev) gpio_direction_output(tegra_host->power_gpio, 1); } - clk = clk_get(mmc_dev(host->mmc), NULL); + clk = devm_clk_get(mmc_dev(host->mmc), NULL); if (IS_ERR(clk)) { dev_err(mmc_dev(host->mmc), "clk err\n"); rc = PTR_ERR(clk); @@ -312,10 +313,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev) err_add_host: clk_disable_unprepare(pltfm_host->clk); - clk_put(pltfm_host->clk); err_clk_get: - if (gpio_is_valid(tegra_host->power_gpio)) - gpio_free(tegra_host->power_gpio); err_power_req: err_parse_dt: err_alloc_tegra_host: @@ -327,16 +325,11 @@ static int sdhci_tegra_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct sdhci_tegra *tegra_host = pltfm_host->priv; int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0x); sdhci_remove_host(host, dead); - if (gpio_is_valid(tegra_host->power_gpio)) - gpio_free(tegra_host->power_gpio); - clk_disable_unprepare(pltfm_host->clk); - clk_put(pltfm_host->clk); sdhci_pltfm_free(pdev); -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 4/7] mmc: sdhci-sirf: kill the "clk" member in driver private struct
Actually we can use the "clk" in the struct sdhci_pltfm_host. With this change we can also kill the private function for get max clock in this driver. Signed-off-by: Kevin Hao --- v2: Also kill the private sdhci_sirf_get_max_clk(). drivers/mmc/host/sdhci-sirf.c | 26 +++--- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/drivers/mmc/host/sdhci-sirf.c b/drivers/mmc/host/sdhci-sirf.c index f6f82ec3618d..c30d6f3dd9aa 100644 --- a/drivers/mmc/host/sdhci-sirf.c +++ b/drivers/mmc/host/sdhci-sirf.c @@ -20,17 +20,9 @@ #define SIRF_TUNING_COUNT 128 struct sdhci_sirf_priv { - struct clk *clk; int gpio_cd; }; -static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host) -{ - struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); - return clk_get_rate(priv->clk); -} - static void sdhci_sirf_set_bus_width(struct sdhci_host *host, int width) { u8 ctrl; @@ -122,7 +114,7 @@ retry: static struct sdhci_ops sdhci_sirf_ops = { .platform_execute_tuning = sdhci_sirf_execute_tuning, .set_clock = sdhci_set_clock, - .get_max_clock = sdhci_sirf_get_max_clk, + .get_max_clock = sdhci_pltfm_clk_get_max_clock, .set_bus_width = sdhci_sirf_set_bus_width, .reset = sdhci_reset, .set_uhs_signaling = sdhci_set_uhs_signaling, @@ -162,13 +154,13 @@ static int sdhci_sirf_probe(struct platform_device *pdev) return PTR_ERR(host); pltfm_host = sdhci_priv(host); + pltfm_host->clk = clk; priv = sdhci_pltfm_priv(pltfm_host); - priv->clk = clk; priv->gpio_cd = gpio_cd; sdhci_get_of_property(pdev); - ret = clk_prepare_enable(priv->clk); + ret = clk_prepare_enable(pltfm_host->clk); if (ret) goto err_clk_prepare; @@ -195,7 +187,7 @@ static int sdhci_sirf_probe(struct platform_device *pdev) err_request_cd: sdhci_remove_host(host, 0); err_sdhci_add: - clk_disable_unprepare(priv->clk); + clk_disable_unprepare(pltfm_host->clk); err_clk_prepare: sdhci_pltfm_free(pdev); return ret; @@ -205,11 +197,9 @@ static int sdhci_sirf_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); + clk_disable_unprepare(pltfm_host->clk); sdhci_pltfm_unregister(pdev); - - clk_disable_unprepare(priv->clk); return 0; } @@ -218,14 +208,13 @@ static int sdhci_sirf_suspend(struct device *dev) { struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); int ret; ret = sdhci_suspend_host(host); if (ret) return ret; - clk_disable(priv->clk); + clk_disable(pltfm_host->clk); return 0; } @@ -234,10 +223,9 @@ static int sdhci_sirf_resume(struct device *dev) { struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct sdhci_sirf_priv *priv = sdhci_pltfm_priv(pltfm_host); int ret; - ret = clk_enable(priv->clk); + ret = clk_enable(pltfm_host->clk); if (ret) { dev_dbg(dev, "Resume: Error enabling clock\n"); return ret; -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 7/7] mmc: sdhci: set the .remove to sdhci_pltfm_unregister()
In these drivers, the driver specific .remove function just a simple wrapper of function sdhci_pltfm_unregister(). So remove these wrappers and just set .remove to sdhci_pltfm_unregister(). Signed-off-by: Kevin Hao --- v2: No change. drivers/mmc/host/sdhci-bcm-kona.c | 7 +-- drivers/mmc/host/sdhci-bcm2835.c | 7 +-- drivers/mmc/host/sdhci-cns3xxx.c | 7 +-- drivers/mmc/host/sdhci-dove.c | 7 +-- drivers/mmc/host/sdhci-of-esdhc.c | 7 +-- drivers/mmc/host/sdhci-of-hlwd.c | 7 +-- drivers/mmc/host/sdhci-sirf.c | 9 + drivers/mmc/host/sdhci-st.c | 7 +-- drivers/mmc/host/sdhci-tegra.c| 7 +-- 9 files changed, 9 insertions(+), 56 deletions(-) diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c index 91cba26f75af..2bd90fb35c75 100644 --- a/drivers/mmc/host/sdhci-bcm-kona.c +++ b/drivers/mmc/host/sdhci-bcm-kona.c @@ -323,11 +323,6 @@ err_pltfm_free: return ret; } -static int sdhci_bcm_kona_remove(struct platform_device *pdev) -{ - return sdhci_pltfm_unregister(pdev); -} - static struct platform_driver sdhci_bcm_kona_driver = { .driver = { .name = "sdhci-kona", @@ -335,7 +330,7 @@ static struct platform_driver sdhci_bcm_kona_driver = { .of_match_table = sdhci_bcm_kona_of_match, }, .probe = sdhci_bcm_kona_probe, - .remove = sdhci_bcm_kona_remove, + .remove = sdhci_pltfm_unregister, }; module_platform_driver(sdhci_bcm_kona_driver); diff --git a/drivers/mmc/host/sdhci-bcm2835.c b/drivers/mmc/host/sdhci-bcm2835.c index 439d259fdf1d..0ef0343c603a 100644 --- a/drivers/mmc/host/sdhci-bcm2835.c +++ b/drivers/mmc/host/sdhci-bcm2835.c @@ -180,11 +180,6 @@ err: return ret; } -static int bcm2835_sdhci_remove(struct platform_device *pdev) -{ - return sdhci_pltfm_unregister(pdev); -} - static const struct of_device_id bcm2835_sdhci_of_match[] = { { .compatible = "brcm,bcm2835-sdhci" }, { } @@ -198,7 +193,7 @@ static struct platform_driver bcm2835_sdhci_driver = { .pm = SDHCI_PLTFM_PMOPS, }, .probe = bcm2835_sdhci_probe, - .remove = bcm2835_sdhci_remove, + .remove = sdhci_pltfm_unregister, }; module_platform_driver(bcm2835_sdhci_driver); diff --git a/drivers/mmc/host/sdhci-cns3xxx.c b/drivers/mmc/host/sdhci-cns3xxx.c index a7935a8d0922..59f2923f8054 100644 --- a/drivers/mmc/host/sdhci-cns3xxx.c +++ b/drivers/mmc/host/sdhci-cns3xxx.c @@ -98,18 +98,13 @@ static int sdhci_cns3xxx_probe(struct platform_device *pdev) return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata, 0); } -static int sdhci_cns3xxx_remove(struct platform_device *pdev) -{ - return sdhci_pltfm_unregister(pdev); -} - static struct platform_driver sdhci_cns3xxx_driver = { .driver = { .name = "sdhci-cns3xxx", .pm = SDHCI_PLTFM_PMOPS, }, .probe = sdhci_cns3xxx_probe, - .remove = sdhci_cns3xxx_remove, + .remove = sdhci_pltfm_unregister, }; module_platform_driver(sdhci_cns3xxx_driver); diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index 2314ff88d942..407c21f152b2 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c @@ -108,11 +108,6 @@ err_sdhci_add: return ret; } -static int sdhci_dove_remove(struct platform_device *pdev) -{ - return sdhci_pltfm_unregister(pdev); -} - static const struct of_device_id sdhci_dove_of_match_table[] = { { .compatible = "marvell,dove-sdhci", }, {} @@ -126,7 +121,7 @@ static struct platform_driver sdhci_dove_driver = { .of_match_table = sdhci_dove_of_match_table, }, .probe = sdhci_dove_probe, - .remove = sdhci_dove_remove, + .remove = sdhci_pltfm_unregister, }; module_platform_driver(sdhci_dove_driver); diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 17fe02ed6672..22e9111b11ff 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -386,11 +386,6 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) return ret; } -static int sdhci_esdhc_remove(struct platform_device *pdev) -{ - return sdhci_pltfm_unregister(pdev); -} - static const struct of_device_id sdhci_esdhc_of_match[] = { { .compatible = "fsl,mpc8379-esdhc" }, { .compatible = "fsl,mpc8536-esdhc" }, @@ -406,7 +401,7 @@ static struct platform_driver sdhci_esdhc_driver = { .pm = ESDHC_PMOPS, }, .probe = sdhci_esdhc_probe, - .remove = sdhci_esdhc_remove, + .remove = sdhci_pltfm_unregister, }; 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 be479279a1d5..4079a9
[PATCH v2 6/7] mmc: sdhci: disable the clock in sdhci_pltfm_unregister()
So we can avoid to sprinkle the clk_disable_unprepare() in many drivers. Signed-off-by: Kevin Hao --- v2: No change. drivers/mmc/host/sdhci-bcm-kona.c | 12 +--- drivers/mmc/host/sdhci-dove.c | 8 +--- drivers/mmc/host/sdhci-of-arasan.c | 1 - drivers/mmc/host/sdhci-pltfm.c | 2 ++ drivers/mmc/host/sdhci-sirf.c | 5 + drivers/mmc/host/sdhci-st.c| 5 - drivers/mmc/host/sdhci-tegra.c | 12 +--- 7 files changed, 6 insertions(+), 39 deletions(-) diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c index 5bc263b447b2..91cba26f75af 100644 --- a/drivers/mmc/host/sdhci-bcm-kona.c +++ b/drivers/mmc/host/sdhci-bcm-kona.c @@ -325,17 +325,7 @@ err_pltfm_free: static int sdhci_bcm_kona_remove(struct platform_device *pdev) { - struct sdhci_host *host = platform_get_drvdata(pdev); - struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host); - int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0x); - - sdhci_remove_host(host, dead); - - clk_disable_unprepare(pltfm_priv->clk); - - sdhci_pltfm_free(pdev); - - return 0; + return sdhci_pltfm_unregister(pdev); } static struct platform_driver sdhci_bcm_kona_driver = { diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index f78440ef1ba4..2314ff88d942 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c @@ -110,13 +110,7 @@ err_sdhci_add: static int sdhci_dove_remove(struct platform_device *pdev) { - struct sdhci_host *host = platform_get_drvdata(pdev); - struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - - clk_disable_unprepare(pltfm_host->clk); - sdhci_pltfm_unregister(pdev); - - return 0; + return sdhci_pltfm_unregister(pdev); } static const struct of_device_id sdhci_dove_of_match_table[] = { diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index bcb51e9dfdcd..129079fb53bf 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -195,7 +195,6 @@ static int sdhci_arasan_remove(struct platform_device *pdev) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_arasan_data *sdhci_arasan = pltfm_host->priv; - clk_disable_unprepare(pltfm_host->clk); clk_disable_unprepare(sdhci_arasan->clk_ahb); return sdhci_pltfm_unregister(pdev); diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index c5b01d6bb85d..74c58d9a4fc8 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c @@ -225,9 +225,11 @@ EXPORT_SYMBOL_GPL(sdhci_pltfm_register); int sdhci_pltfm_unregister(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) == 0x); sdhci_remove_host(host, dead); + clk_disable_unprepare(pltfm_host->clk); sdhci_pltfm_free(pdev); return 0; diff --git a/drivers/mmc/host/sdhci-sirf.c b/drivers/mmc/host/sdhci-sirf.c index c30d6f3dd9aa..f7dd68e55b49 100644 --- a/drivers/mmc/host/sdhci-sirf.c +++ b/drivers/mmc/host/sdhci-sirf.c @@ -196,11 +196,8 @@ err_clk_prepare: static int sdhci_sirf_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); - struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - clk_disable_unprepare(pltfm_host->clk); - sdhci_pltfm_unregister(pdev); - return 0; + return sdhci_pltfm_unregister(pdev); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index 882b07e9667e..0019df452522 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c @@ -115,11 +115,6 @@ err_of: static int sdhci_st_remove(struct platform_device *pdev) { - struct sdhci_host *host = platform_get_drvdata(pdev); - struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - - clk_disable_unprepare(pltfm_host->clk); - return sdhci_pltfm_unregister(pdev); } diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 0643f66b4e14..12881e05ff30 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -323,17 +323,7 @@ err_alloc_tegra_host: static int sdhci_tegra_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) == 0x); - - sdhci_remove_host(host, dead); - - clk_disable_unprepare(pltfm_host->clk); - - sdhci_pltfm_free(pdev); - - return 0; + return sdhci_pltfm_unregister(pdev); } static struct platform_driver sdhci_tegra_driver = { -- 1.9.3 -- To
[PATCH v2 5/7] mmc: sdhci-bcm-kona: kill the "external_clk" member in driver private struct
Actually we can use the "clk" in the struct sdhci_pltfm_host. Also change the "external clock" to "core clock" and kill two redundant private functions in this driver as suggested by Ray Jui. Signed-off-by: Kevin Hao --- v2: - s/external clock/core clock/ - kill the private functions sdhci_bcm_kona_get_max_clk() and sdhci_bcm_kona_get_timeout_clock() drivers/mmc/host/sdhci-bcm-kona.c | 46 +++ 1 file changed, 13 insertions(+), 33 deletions(-) diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c index 34bb8f92586e..5bc263b447b2 100644 --- a/drivers/mmc/host/sdhci-bcm-kona.c +++ b/drivers/mmc/host/sdhci-bcm-kona.c @@ -54,7 +54,6 @@ struct sdhci_bcm_kona_dev { struct mutexwrite_lock; /* protect back to back writes */ - struct clk *external_clk; }; @@ -175,24 +174,6 @@ static void sdhci_bcm_kona_card_event(struct sdhci_host *host) } } -/* - * Get the base clock. Use central clock source for now. Not sure if different - * clock speed to each dev is allowed - */ -static unsigned int sdhci_bcm_kona_get_max_clk(struct sdhci_host *host) -{ - struct sdhci_bcm_kona_dev *kona_dev; - struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host); - kona_dev = sdhci_pltfm_priv(pltfm_priv); - - return host->mmc->f_max; -} - -static unsigned int sdhci_bcm_kona_get_timeout_clock(struct sdhci_host *host) -{ - return sdhci_bcm_kona_get_max_clk(host); -} - static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host, u8 power_mode) { @@ -207,8 +188,8 @@ static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host, static struct sdhci_ops sdhci_bcm_kona_ops = { .set_clock = sdhci_set_clock, - .get_max_clock = sdhci_bcm_kona_get_max_clk, - .get_timeout_clock = sdhci_bcm_kona_get_timeout_clock, + .get_max_clock = sdhci_pltfm_clk_get_max_clock, + .get_timeout_clock = sdhci_pltfm_clk_get_max_clock, .platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, @@ -264,21 +245,21 @@ static int sdhci_bcm_kona_probe(struct platform_device *pdev) goto err_pltfm_free; } - /* Get and enable the external clock */ - kona_dev->external_clk = devm_clk_get(dev, NULL); - if (IS_ERR(kona_dev->external_clk)) { - dev_err(dev, "Failed to get external clock\n"); - ret = PTR_ERR(kona_dev->external_clk); + /* Get and enable the core clock */ + pltfm_priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(pltfm_priv->clk)) { + dev_err(dev, "Failed to get core clock\n"); + ret = PTR_ERR(pltfm_priv->clk); goto err_pltfm_free; } - if (clk_set_rate(kona_dev->external_clk, host->mmc->f_max) != 0) { - dev_err(dev, "Failed to set rate external clock\n"); + if (clk_set_rate(pltfm_priv->clk, host->mmc->f_max) != 0) { + dev_err(dev, "Failed to set rate core clock\n"); goto err_pltfm_free; } - if (clk_prepare_enable(kona_dev->external_clk) != 0) { - dev_err(dev, "Failed to enable external clock\n"); + if (clk_prepare_enable(pltfm_priv->clk) != 0) { + dev_err(dev, "Failed to enable core clock\n"); goto err_pltfm_free; } @@ -333,7 +314,7 @@ err_reset: sdhci_bcm_kona_sd_reset(host); err_clk_disable: - clk_disable_unprepare(kona_dev->external_clk); + clk_disable_unprepare(pltfm_priv->clk); err_pltfm_free: sdhci_pltfm_free(pdev); @@ -346,12 +327,11 @@ static int sdhci_bcm_kona_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host); - struct sdhci_bcm_kona_dev *kona_dev = sdhci_pltfm_priv(pltfm_priv); int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0x); sdhci_remove_host(host, dead); - clk_disable_unprepare(kona_dev->external_clk); + clk_disable_unprepare(pltfm_priv->clk); sdhci_pltfm_free(pdev); -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 2/7] mmc: sdhci-dove: kill the driver specific private struct
There is only one "clk" member in this driver specific private struct. Actually we can use the "clk" member in the struct sdhci_pltfm_host, and then kill this struct completely. Signed-off-by: Kevin Hao --- v2: No change. drivers/mmc/host/sdhci-dove.c | 26 +- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index 0a7aeb162497..f78440ef1ba4 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c @@ -28,10 +28,6 @@ #include "sdhci-pltfm.h" -struct sdhci_dove_priv { - struct clk *clk; -}; - static u16 sdhci_dove_readw(struct sdhci_host *host, int reg) { u16 ret; @@ -84,27 +80,17 @@ static int sdhci_dove_probe(struct platform_device *pdev) { struct sdhci_host *host; struct sdhci_pltfm_host *pltfm_host; - struct sdhci_dove_priv *priv; int ret; - priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv), - GFP_KERNEL); - if (!priv) { - dev_err(&pdev->dev, "unable to allocate private data"); - return -ENOMEM; - } - - priv->clk = devm_clk_get(&pdev->dev, NULL); - host = sdhci_pltfm_init(pdev, &sdhci_dove_pdata, 0); if (IS_ERR(host)) return PTR_ERR(host); pltfm_host = sdhci_priv(host); - pltfm_host->priv = priv; + pltfm_host->clk = devm_clk_get(&pdev->dev, NULL); - if (!IS_ERR(priv->clk)) - clk_prepare_enable(priv->clk); + if (!IS_ERR(pltfm_host->clk)) + clk_prepare_enable(pltfm_host->clk); ret = mmc_of_parse(host->mmc); if (ret) @@ -117,7 +103,7 @@ static int sdhci_dove_probe(struct platform_device *pdev) return 0; err_sdhci_add: - clk_disable_unprepare(priv->clk); + clk_disable_unprepare(pltfm_host->clk); sdhci_pltfm_free(pdev); return ret; } @@ -126,12 +112,10 @@ static int sdhci_dove_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct sdhci_dove_priv *priv = pltfm_host->priv; + clk_disable_unprepare(pltfm_host->clk); sdhci_pltfm_unregister(pdev); - clk_disable_unprepare(priv->clk); - return 0; } -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 0/7] mmc: sdhci: set .remove to sdhci_pltfm_unregister()
Hi, v2: - Update the sdhci-bcm-kona as suggested by Ray Jui. - Also kill the private get_max_clock function in sdhci-sirf. v1: In the current kernel, the specific .remove function in several sdhci platform drivers seem pretty similar. Actually we can just set all of them to sdhci_pltfm_unregister() with just a bit twist. Only run test for sdhci-of-esdhc driver. All others just passed the build test. Kevin Hao (7): mmc: sdhci-dove: remove the unneeded error check mmc: sdhci-dove: kill the driver specific private struct mmc: tegra: use devm help functions to get the clk and gpio mmc: sdhci-sirf: kill the "clk" member in driver private struct mmc: sdhci-bcm-kona: kill the "external_clk" member in driver private struct mmc: sdhci: disable the clock in sdhci_pltfm_unregister() mmc: sdhci: set the .remove to sdhci_pltfm_unregister() drivers/mmc/host/sdhci-bcm-kona.c | 61 -- drivers/mmc/host/sdhci-bcm2835.c | 7 + drivers/mmc/host/sdhci-cns3xxx.c | 7 + drivers/mmc/host/sdhci-dove.c | 39 drivers/mmc/host/sdhci-of-arasan.c | 1 - drivers/mmc/host/sdhci-of-esdhc.c | 7 + drivers/mmc/host/sdhci-of-hlwd.c | 7 + drivers/mmc/host/sdhci-pltfm.c | 2 ++ drivers/mmc/host/sdhci-sirf.c | 36 +- drivers/mmc/host/sdhci-st.c| 12 +--- drivers/mmc/host/sdhci-tegra.c | 30 +++ 11 files changed, 36 insertions(+), 173 deletions(-) -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/7] mmc: sdhci-dove: remove the unneeded error check
The function clk_disable_unprepare() already take care of either error or null cases. Signed-off-by: Kevin Hao --- v2: No change. drivers/mmc/host/sdhci-dove.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index ca969d271a27..0a7aeb162497 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c @@ -117,8 +117,7 @@ static int sdhci_dove_probe(struct platform_device *pdev) return 0; err_sdhci_add: - if (!IS_ERR(priv->clk)) - clk_disable_unprepare(priv->clk); + clk_disable_unprepare(priv->clk); sdhci_pltfm_free(pdev); return ret; } @@ -131,8 +130,7 @@ static int sdhci_dove_remove(struct platform_device *pdev) sdhci_pltfm_unregister(pdev); - if (!IS_ERR(priv->clk)) - clk_disable_unprepare(priv->clk); + clk_disable_unprepare(priv->clk); return 0; } -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [patch] mmc: sdhci-esdhc-imx: silence a false curly braces warning
On Thu, Feb 26, 2015 at 11:37:55PM +0300, Dan Carpenter wrote: > Static checkers suggest that probably we intended to put curly braces > around the writel() to make it part of the else path. But, I think > actually the indenting is off and the code works fine as is. > > The stray tab was introduced in 0322191e6298 ('mmc: sdhci-esdhc-imx: add > sd3.0 SDR clock tuning support') > > Signed-off-by: Dan Carpenter > Yes, that's a mistake. Thanks for the finding. Acked-by: Dong Aisheng Regards Dong Aisheng > diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c > b/drivers/mmc/host/sdhci-esdhc-imx.c > index 10ef824..9cce5cf 100644 > --- a/drivers/mmc/host/sdhci-esdhc-imx.c > +++ b/drivers/mmc/host/sdhci-esdhc-imx.c > @@ -416,7 +416,7 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 > val, int reg) > new_val |= ESDHC_VENDOR_SPEC_FRC_SDCLK_ON; > else > new_val &= ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON; > - writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); > + writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); > return; > case SDHCI_HOST_CONTROL2: > new_val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] mmc: dw_mmc: fix bug that cause mmc_test failture
Hi, I will apply into my-tree after change the subject and fix typo. Acked-by: Jaehoon Chung Best Regards, Jaehoon Chung On 02/26/2015 03:17 AM, Javier Martinez Canillas wrote: > Hello Addy, > > On 02/20/2015 03:55 AM, Addy Ke wrote: >> The STOP command can terminate a data transfer between a memory card and >> mmc controller. >> >> As show in Synopsys DesignWare Cores Mobile Stroage Host Databook: > > s/Stroage/Storage but maybe Ulf can amend the typo when applying? > >> Data timeout and Data end-bit error will terminate further data transfer >> by mmc controller. So we should not send abort command to terminate a >> data transfer again if we got DRTO and EBE interrupt. >> >> After this patch, all mmc_test cases can pass on RK3288-Pink2 board. >> >> Signed-off-by: Addy Ke > > I did not run all the tests listed in /sys/kernel/debug/mmc*/*/testlist > because some of them will overwrite the data in my card but at least > the read ones completed successfully and $subject does not cause a > regression in the Exynos5250 Snow, Exynos5420 Peach Pit and Exynos5800 > Peach Pi Chromebooks where I tested it. > > Tested-by: Javier Martinez Canillas > > Best regards, > Javier > -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH] mmc: mmc_oops: support mmc_oops feature
When kernel is occurred the panic or oops, then save the panic/oops log into eMMC card. Signed-off-by: Jaehoon Chung Signed-off-by: Kyungmin Park --- Documentation/devicetree/bindings/mmc/mmcoops.txt | 23 ++ drivers/mmc/card/Kconfig |8 + drivers/mmc/card/Makefile |1 + drivers/mmc/card/block.c |4 + drivers/mmc/card/mmc_oops.c | 304 + drivers/mmc/core/core.c | 27 ++ include/linux/mmc/card.h |3 + include/linux/mmc/core.h |3 + 8 files changed, 373 insertions(+) create mode 100644 Documentation/devicetree/bindings/mmc/mmcoops.txt create mode 100644 drivers/mmc/card/mmc_oops.c diff --git a/Documentation/devicetree/bindings/mmc/mmcoops.txt b/Documentation/devicetree/bindings/mmc/mmcoops.txt new file mode 100644 index 000..236f6ec --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/mmcoops.txt @@ -0,0 +1,23 @@ +* Mmcoops oops/panic logger + +Mmcoops is an oops/panic logger that write its logs to MMC before the system crashes. +Introduction and concept are similar to other oops logger. +(Refer to Documention/ramoops.txt) +- Disadvantage: if MMC is occurred an oops/panic, this logger can't work. + +After reboot, you can get the last log with below command. +#dd if=/dev/mmcblk0 of=/tmp/dump.log skip=64 count=16 +#vi dump.log + +Required Properties: + +* compatible: should be "mmcoops" +* start-offset: block-offset for start. +* size: the number of block to write oopses and panics. + +Example: + mmcoops { + compatible = "mmcoops"; + start-offest = <64>;/* 64 * 512B = 32KiB offset */ + size = <16>;/* 16 * 512B = 8KiB */ + }; diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig index 5562308..3895dc1 100644 --- a/drivers/mmc/card/Kconfig +++ b/drivers/mmc/card/Kconfig @@ -68,3 +68,11 @@ config MMC_TEST This driver is only of interest to those developing or testing a host driver. Most people should say N here. + +config MMC_OOPS + tristate "Log panic/oops to a MMC buffer" + depends on OF + help + This enables panic and oops messages to be logged to a circular + buffer in a MMC sectors where it can be read back at some + later point. diff --git a/drivers/mmc/card/Makefile b/drivers/mmc/card/Makefile index c73b406..f88a085 100644 --- a/drivers/mmc/card/Makefile +++ b/drivers/mmc/card/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_MMC_BLOCK)+= mmc_block.o mmc_block-objs := block.o queue.o obj-$(CONFIG_MMC_TEST) += mmc_test.o +obj-$(CONFIG_MMC_OOPS) += mmc_oops.o obj-$(CONFIG_SDIO_UART)+= sdio_uart.o diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index c69afb5..61a2135 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -2447,6 +2447,10 @@ static int mmc_blk_probe(struct device *dev) dev_set_drvdata(dev, md); +#ifdef CONFIG_MMC_OOPS + if (mmc_card_mmc(card)) + mmc_oops_card_set(card); +#endif if (mmc_add_disk(md)) goto out; diff --git a/drivers/mmc/card/mmc_oops.c b/drivers/mmc/card/mmc_oops.c new file mode 100644 index 000..db09b47 --- /dev/null +++ b/drivers/mmc/card/mmc_oops.c @@ -0,0 +1,304 @@ +/* + * MMC Oops/Panic logger + * + * Copyright (C) 2010-2015 Samsung Electronics + * Jaehoon Chung + * Kyungmin Park + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* TODO Unify the oops header, mmtoops, ramoops, mmcoops */ +#define MMCOOPS_KERNMSG_HDR"" +#define MMCOOPS_HEADER_SIZE(5 + sizeof(struct timeval)) + +#define RECORD_SIZE4096 + +static int dump_oops = 1; +module_param(dump_oops, int, 0600); +MODULE_PARM_DESC(dump_oops, + "set to 1 to dump oopses, 0 to only dump panics (default 1)"); + +#define dev_to_mmc_card(d) container_of(d, struct mmc_card, dev) + +static struct mmcoops_context { + struct kmsg_dumper dump; + struct mmc_card *card; + unsigned long start; + unsigned long size; + struct device *dev; + struct platform_device *pdev; + int count; + int max_count; + void*virt_addr; +} oops_cxt; + +static void mmc_panic_write(struct mmcoops_context *cxt, + char *buf, unsigned long start, unsigned int size) +{ + struct mmc_card *card = cxt->c
[patch] mmc: sdhci-esdhc-imx: silence a false curly braces warning
Static checkers suggest that probably we intended to put curly braces around the writel() to make it part of the else path. But, I think actually the indenting is off and the code works fine as is. The stray tab was introduced in 0322191e6298 ('mmc: sdhci-esdhc-imx: add sd3.0 SDR clock tuning support') Signed-off-by: Dan Carpenter diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 10ef824..9cce5cf 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -416,7 +416,7 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg) new_val |= ESDHC_VENDOR_SPEC_FRC_SDCLK_ON; else new_val &= ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON; - writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); + writel(new_val, host->ioaddr + ESDHC_VENDOR_SPEC); return; case SDHCI_HOST_CONTROL2: new_val = readl(host->ioaddr + ESDHC_VENDOR_SPEC); -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/3] extract PARTITION_SETTING_COMPLETE function
Ben Gardiner gmail.com> writes: > > Extract a function which sets the OTP PARTITION_SETTING_COMPLETE > bit; once this bit is set there are many other parameters in > EXT_CSD which can no longer be set. > > Multiple OTP partition settings can be achieved by calling 'set' > commands with '-n' on all except for the last. > > Signed-off-by: Ben Gardiner gmail.com> > --- > mmc_cmds.c | 77 ++--- - > 1 file changed, 47 insertions(+), 30 deletions(-) > > diff --git a/mmc_cmds.c b/mmc_cmds.c > index ba4f9cf..5ea19ac 100644 > --- a/mmc_cmds.c > +++ b/mmc_cmds.c > -449,6 +449,51 unsigned int get_hc_erase_grp_size(__u8 *ext_csd) > return ext_csd[224]; > } > > +int set_partitioning_setting_completed(int dry_run, const char * const device, > + int fd) > +{ > + int ret; > + > + if (dry_run) { > + fprintf(stderr, "NOT setting PARTITION_SETTING_COMPLETED\n"); > + fprintf(stderr, "These changes will not take effect neither " > + "now nor after a power cycle\n"); > + return 1; > + } > + > + fprintf(stderr, "setting OTP PARTITION_SETTING_COMPLETED!\n"); > + ret = write_extcsd_value(fd, EXT_CSD_PARTITION_SETTING_COMPLETED, 0x1); > + if (ret) { > + fprintf(stderr, "Could not write 0x1 to " > + "EXT_CSD[%d] in %s\n", > + EXT_CSD_PARTITION_SETTING_COMPLETED, device); > + return 1; > + } > + > + __u32 response; > + ret = send_status(fd, &response); > + if (ret) { > + fprintf(stderr, "Could not get response to SEND_STATUS " > + "from %s\n", device); > + return 1; > + } > + > + if (response & R1_SWITCH_ERROR) { > + fprintf(stderr, "Setting OTP PARTITION_SETTING_COMPLETED " > + "failed on %s\n", device); > + return 1; > + } > + > + fprintf(stderr, "Setting OTP PARTITION_SETTING_COMPLETED on " > + "%s SUCCESS\n", device); > + fprintf(stderr, "Device power cycle needed for settings to " > + "take effect.\n" > + "Confirm that PARTITION_SETTING_COMPLETED bit is set " > + "using 'extcsd read' after power cycle\n"); > + > + return 0; > +} > + > int do_enh_area_set(int nargs, char **argv) > { > __u8 value; > -579,38 +624,10 int do_enh_area_set(int nargs, char **argv) > exit(1); > } > > - if (dry_run) > - { > - fprintf(stderr, "NOT setting PARTITION_SETTING_COMPLETED\n"); > - exit(1); > - } > + printf("Done setting ENH_USR area on %s\n", device); > > - fprintf(stderr, "setting OTP PARTITION_SETTING_COMPLETED!\n"); > - ret = write_extcsd_value(fd, EXT_CSD_PARTITION_SETTING_COMPLETED, 0x1); > - if (ret) { > - fprintf(stderr, "Could not write 0x1 to " > - "EXT_CSD[%d] in %s\n", > - EXT_CSD_PARTITION_SETTING_COMPLETED, device); > + if (!set_partitioning_setting_completed(dry_run, device, fd)) > exit(1); > - } > - > - __u32 response; > - ret = send_status(fd, &response); > - if (ret) { > - fprintf(stderr, "Could not get response to SEND_STATUS from %s\n", device); > - exit(1); > - } > - > - if (response & R1_SWITCH_ERROR) > - { > - fprintf(stderr, "Setting ENH_USR area failed on %s\n", device); > - exit(1); > - } > - > - fprintf(stderr, "Setting ENH_USR area on %s SUCCESS\n", device); > - fprintf(stderr, "Device power cycle needed for settings to take effect.\n" > - "Confirm that PARTITION_SETTING_COMPLETED bit is set using 'extcsd read'" > - "after power cycle\n"); > > return 0; > } The program return code looks wrong with this patch. If I do mmc write_reliability set -n 0 /dev/mmcblk0; echo $? mmc write_reliability set -y 0 /dev/mmcblk0; echo $? the first instance returns a 0, the second a 1. The following change fixes this by changing set_partitioning_setting completed() to only return one on an error and removing the inversions in the if tests. mmc_cmds.c |6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mmc_cmds.c b/mmc_cmds.c index cea943f..c4efffe 100644 --- a/mmc_cmds.c +++ b/mmc_cmds.c @@ -462,7 +462,7 @@ int set_partitioning_setting_completed(int dry_run, const char * const device, fprintf(stderr, "NOT setting PARTITION_SETTING_COMPLETED\n"); fprintf(stderr, "These changes will not take effect neither " "now nor after a power cycle\n"); - return 1; + return 0; } fprintf(stderr, "setting OTP PARTITION_SETTING_COMPLETED!\n"); @@ -630,7 +630,7 @@ int do_enh_area_set(int nargs, char **argv) printf
Re: [PATCH 0/4] Add support for IPROC SDHCI controller
Hi Chris, I have not heard any more feedback on this patchset. Is it in your queue to review or merge into your tree? Thanks, Scott On 15-02-09 04:06 PM, Scott Branden wrote: This series of patchsets contains the IPROC SDHCI driver used in a series of Broadcom SoCs Quirks are also added to support this controller. Corneliu Doban (1): mmc: sdhci: do not set AUTO_CMD12 for multi-block CMD53 Scott Branden (3): mmc: sdhci: add quirk for ACMD23 broken mmc: sdhci-iproc: add IPROC SDHCI driver mmc: sdhci-iproc: add device tree bindings .../devicetree/bindings/mmc/brcm,sdhci-iproc.txt | 23 ++ drivers/mmc/host/Kconfig | 14 ++ drivers/mmc/host/Makefile | 1 + drivers/mmc/host/sdhci-iproc.c | 241 + drivers/mmc/host/sdhci.c | 7 +- include/linux/mmc/sdhci.h | 2 + 6 files changed, 286 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt create mode 100644 drivers/mmc/host/sdhci-iproc.c -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 0/8] Add sd/emmc support for stih407 family silicon
Hi, This series adds sd/emmc support to the sdhci-st.c driver for stih407 family silicon. The changes mainly involve congiguring some extra glue registers in the flashSS which configure the Arasan controller. This series also adds support for UHS modes for eMMC. To allow UHS HS200/SD104 modes to function correctly, due to the tight timing constriants, support for delay management is also added. Two types of delay management are supported, static delay management and dynamic delay management, this delay management is only available on eMMC pads on stih410 and later silicon. This series has been tested with stih410-b2120 on eMMC and sd, at various clock speeds. As part of this testing a bug was also found in the upstream flexgen clock set_rate implementation (now fixed upstream). max-frequency = 200Mhz /dev/mmcblk0p1: Timing buffered disk reads: 270 MB in 3.02 seconds = 89.54 MB/sec max-frequency = 100Mhz root@debian-armhf:~# hdparm -t /dev/mmcblk0p1 /dev/mmcblk0p1: Timing buffered disk reads: 210 MB in 3.00 seconds = 70.00 MB/sec max-frequency = 50Mhz root@debian-armhf:~# hdparm -t /dev/mmcblk0p1 /dev/mmcblk0p1: Timing buffered disk reads: 118 MB in 3.00 seconds = 39.28 MB/sec It has also been tested on stih416-b2020 to ensure we have caused no regressions. Finally the dt documentation has been updated to reflect the changes in the driver code. Intrestingly it seems we are the first upstream platform to be using some of the uhs bindings such as sd-uhs-sdr104. Changes since v1: - Partition the changes into smaller patches to aid review process (Ulf) regards, Peter. Peter Griffin (8): mmc: sdhci-st: Add macros for register offsets and bitfields for mmcss glue regs mmc: sdhci-st: Add support for de-asserting reset signal and top regs resource mmc: sdhci-st: Add delay management functions for top registers (eMMC). mmc: sdhci-st: Add st_mmcss_cconfig function to configure mmcss glue registers. mmc: sdhci-st: Add sdhci_st_set_uhs_signaling function. mmc: sdhci-st: Update the quirks for this controller. mmc: sdhci-st: Update ST SDHCI binding documentation. ARM: STi: DT: STiH407: Add dt nodes for sdhci and emmc. Documentation/devicetree/bindings/mmc/sdhci-st.txt | 100 +- arch/arm/boot/dts/stih407-family.dtsi | 30 ++ arch/arm/boot/dts/stih410-b2120.dts| 10 + arch/arm/boot/dts/stihxxx-b2120.dtsi | 8 + drivers/mmc/host/sdhci-st.c| 344 - 5 files changed, 478 insertions(+), 14 deletions(-) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/8] mmc: sdhci-st: Add macros for register offsets and bitfields for mmcss glue regs
The stih407 family SoC's have additional glue registers in the flashSS which are used to configure the Arasan controller. This patch adds macros for the register offsets and bitfields which will be used by subsequent patches to support stih407 family SoC's. Signed-off-by: Peter Griffin Signed-off-by: Giuseppe Cavallaro --- drivers/mmc/host/sdhci-st.c | 91 + 1 file changed, 91 insertions(+) diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index 882b07e..a3bc3c3 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c @@ -26,6 +26,97 @@ #include "sdhci-pltfm.h" +/* MMCSS glue logic to setup the HC on some ST SoCs (e.g. STiH407 family) */ + +#defineST_MMC_CCONFIG_REG_10x400 +#define ST_MMC_CCONFIG_TIMEOUT_CLK_UNITBIT(24) +#define ST_MMC_CCONFIG_TIMEOUT_CLK_FREQBIT(12) +#define ST_MMC_CCONFIG_TUNING_COUNT_DEFAULTBIT(8) +#define ST_MMC_CCONFIG_ASYNC_WAKEUPBIT(0) +#define ST_MMC_CCONFIG_1_DEFAULT \ + ((ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT) | \ +(ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ) | \ +(ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT)) + +#define ST_MMC_CCONFIG_REG_2 0x404 +#define ST_MMC_CCONFIG_HIGH_SPEED BIT(28) +#define ST_MMC_CCONFIG_ADMA2 BIT(24) +#define ST_MMC_CCONFIG_8BITBIT(20) +#define ST_MMC_CCONFIG_MAX_BLK_LEN 16 +#define MAX_BLK_LEN_1024 1 +#define MAX_BLK_LEN_2048 2 +#define BASE_CLK_FREQ_200 0xc8 +#define BASE_CLK_FREQ_100 0x64 +#define BASE_CLK_FREQ_50 0x32 +#define ST_MMC_CCONFIG_2_DEFAULT \ + (ST_MMC_CCONFIG_HIGH_SPEED | ST_MMC_CCONFIG_ADMA2 | \ +ST_MMC_CCONFIG_8BIT | \ +(MAX_BLK_LEN_1024 << ST_MMC_CCONFIG_MAX_BLK_LEN)) + +#define ST_MMC_CCONFIG_REG_3 0x408 +#define ST_MMC_CCONFIG_EMMC_SLOT_TYPE BIT(28) +#define ST_MMC_CCONFIG_64BIT BIT(24) +#define ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT BIT(20) +#define ST_MMC_CCONFIG_1P8_VOLTBIT(16) +#define ST_MMC_CCONFIG_3P0_VOLTBIT(12) +#define ST_MMC_CCONFIG_3P3_VOLTBIT(8) +#define ST_MMC_CCONFIG_SUSP_RES_SUPPORTBIT(4) +#define ST_MMC_CCONFIG_SDMABIT(0) +#define ST_MMC_CCONFIG_3_DEFAULT \ +(ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT| \ + ST_MMC_CCONFIG_3P3_VOLT | \ + ST_MMC_CCONFIG_SUSP_RES_SUPPORT | \ + ST_MMC_CCONFIG_SDMA) + +#define ST_MMC_CCONFIG_REG_4 0x40c +#define ST_MMC_CCONFIG_D_DRIVERBIT(20) +#define ST_MMC_CCONFIG_C_DRIVERBIT(16) +#define ST_MMC_CCONFIG_A_DRIVERBIT(12) +#define ST_MMC_CCONFIG_DDR50 BIT(8) +#define ST_MMC_CCONFIG_SDR104 BIT(4) +#define ST_MMC_CCONFIG_SDR50 BIT(0) +#define ST_MMC_CCONFIG_4_DEFAULT 0 + +#define ST_MMC_CCONFIG_REG_5 0x410 +#define ST_MMC_CCONFIG_TUNING_FOR_SDR50BIT(8) +#define RETUNING_TIMER_CNT_MAX 0xf +#define ST_MMC_CCONFIG_5_DEFAULT 0 + +/* I/O configuration for Arasan IP */ +#defineST_MMC_GP_OUTPUT0x450 +#define ST_MMC_GP_OUTPUT_CDBIT(12) + +#define ST_MMC_STATUS_R0x460 + +#define ST_TOP_MMC_DLY_FIX_OFF(x) (x - 0x8) + +/* TOP config registers to manage static and dynamic delay */ +#defineST_TOP_MMC_TX_CLK_DLY ST_TOP_MMC_DLY_FIX_OFF(0x8) +#defineST_TOP_MMC_RX_CLK_DLY ST_TOP_MMC_DLY_FIX_OFF(0xc) +/* MMC delay control register */ +#defineST_TOP_MMC_DLY_CTRL ST_TOP_MMC_DLY_FIX_OFF(0x18) +#defineST_TOP_MMC_DLY_CTRL_DLL_BYPASS_CMD BIT(0) +#defineST_TOP_MMC_DLY_CTRL_DLL_BYPASS_PH_SEL BIT(1) +#defineST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE BIT(8) +#defineST_TOP_MMC_DLY_CTRL_RX_DLL_ENABLE BIT(9) +#defineST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY BIT(10) +#defineST_TOP_MMC_START_DLL_LOCK BIT(11) + +/* register to provide the phase-shift value for DLL */ +#defineST_TOP_MMC_TX_DLL_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x1c) +#defineST_TOP_MMC_RX_DLL_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x20) +#defineST_TOP_MMC_RX_CMD_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x24) + +/* phase shift delay on the tx clk 2.188ns */ +#defineST_TOP_MMC_TX_DLL_STEP_DLY_VALID0x6 + +#defineST_TOP_MMC_DLY_MAX 0xf + +#define ST_TOP_MMC_DYN_DLY_CONF\ + (ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE | \ +ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY | \ +ST_TOP_MMC_START_DLL_LOCK) + static u32 sdhci_st_readl(struct sdhci_host *host, int reg) { u32
[PATCH v2 7/8] mmc: sdhci-st: Update ST SDHCI binding documentation.
This patch updates the binding information to reflect the extra dt options which are now supported by the sdhci-st.c driver which enable support for stih407 family silicon. Stih410 SoC and later support UHS modes for eMMC, so the driver now makes use of these common bindings. Examples are provided for both eMMC (which has additional bindings) and also sd slot for stih407. Signed-off-by: Peter Griffin --- Documentation/devicetree/bindings/mmc/sdhci-st.txt | 100 ++--- 1 file changed, 90 insertions(+), 10 deletions(-) diff --git a/Documentation/devicetree/bindings/mmc/sdhci-st.txt b/Documentation/devicetree/bindings/mmc/sdhci-st.txt index 7527db4..18d950d 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-st.txt +++ b/Documentation/devicetree/bindings/mmc/sdhci-st.txt @@ -5,20 +5,62 @@ Documentation/devicetree/bindings/mmc/mmc.txt and the properties used by the sdhci-st driver. Required properties: -- compatible : Must be "st,sdhci" -- clock-names : Should be "mmc" -See: Documentation/devicetree/bindings/resource-names.txt -- clocks : Phandle of the clock used by the sdhci controler -See: Documentation/devicetree/bindings/clock/clock-bindings.txt +- compatible: Must be "st,sdhci" and it can be compatible to "st,sdhci-stih407" + to set the internal glue logic used for configuring the MMC + subsystem (mmcss) inside the FlashSS (available in STiH407 SoC + family). + +- clock-names: Should be "mmc". + See: Documentation/devicetree/bindings/resource-names.txt +- clocks: Phandle to the clock. + See: Documentation/devicetree/bindings/clock/clock-bindings.txt + +- interrupts: One mmc interrupt should be described here. +- interrupt-names: Should be "mmcirq". + +- pinctrl-names: A pinctrl state names "default" must be defined. +- pinctrl-0: Phandle referencing pin configuration of the sd/emmc controller. + See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt + +- reg: This must provide the host controller base address and it can also + contain the FlashSS Top register for TX/RX delay used by the driver + to configure DLL inside the flashSS, if so reg-names must also be + specified. Optional properties: -- non-removable: non-removable slot - See: Documentation/devicetree/bindings/mmc/mmc.txt -- bus-width: Number of data lines - See: Documentation/devicetree/bindings/mmc/mmc.txt +- reg-names: Should be "mmc" and "top-mmc-delay". "top-mmc-delay" is optional + for eMMC on stih407 family silicon to configure DLL inside FlashSS. + +- non-removable: Non-removable slot. Also used for configuring mmcss in STiH407 SoC + family. + See: Documentation/devicetree/bindings/mmc/mmc.txt. + +- bus-width: Number of data lines. + See: Documentation/devicetree/bindings/mmc/mmc.txt. + +- max-frequency: Can be 200MHz, 100Mz or 50MHz (default) and used for + configuring the CCONFIG3 in the mmcss. + See: Documentation/devicetree/bindings/mmc/mmc.txt. + +- resets: Phandle and reset specifier pair to softreset line of HC IP. + See: Documentation/devicetree/bindings/reset/reset.txt + +- vqmmc-supply:Phandle to the regulator dt node, mentioned as the vcc/vdd + supply in eMMC/SD specs. + +- sd-uhs--sdr50: To enable the SDR50 in the mmcss. + See: Documentation/devicetree/bindings/mmc/mmc.txt. + +- sd-uhs-sdr104: To enable the SDR104 in the mmcss. + See: Documentation/devicetree/bindings/mmc/mmc.txt. + +- sd-uhs-ddr50:To enable the DDR50 in the mmcss. + See: Documentation/devicetree/bindings/mmc/mmc.txt. Example: +/* Example stih416e eMMC configuration */ + mmc0: sdhci@fe81e000 { compatible = "st,sdhci"; status = "disabled"; @@ -29,5 +71,43 @@ mmc0: sdhci@fe81e000 { pinctrl-0 = <&pinctrl_mmc0>; clock-names = "mmc"; clocks = <&clk_s_a1_ls 1>; - bus-width = <8> + bus-width = <8> + +/* Example SD stih407 family configuration */ + +mmc1: sdhci@0908 { + compatible = "st,sdhci-stih407", "st,sdhci"; + status = "disabled"; + reg = <0x0908 0x7ff>; + reg-names = "mmc"; + interrupts = ; + interrupt-names = "mmcirq"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sd1>; + clock-names = "mmc"; + clocks
[PATCH v2 2/8] mmc: sdhci-st: Add support for de-asserting reset signal and top regs resource
STiH407 family SoC's can have a reset signal for the controller which needs to be managed. Also the eMMC controller has some additional 'top' memory mapped registers which are used to manage the dynamic and static delay required for UHS modes. This patch adds support for creating the mapping, which will be used by subsequent patches. Signed-off-by: Peter Griffin Signed-off-by: Giuseppe Cavallaro --- drivers/mmc/host/sdhci-st.c | 52 ++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index a3bc3c3..0101ae9 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c @@ -23,9 +23,14 @@ #include #include #include - +#include #include "sdhci-pltfm.h" +struct st_mmc_platform_data { + struct reset_control *rstc; + void __iomem *top_ioaddr; +}; + /* MMCSS glue logic to setup the HC on some ST SoCs (e.g. STiH407 family) */ #defineST_MMC_CCONFIG_REG_10x400 @@ -151,10 +156,16 @@ static const struct sdhci_pltfm_data sdhci_st_pdata = { static int sdhci_st_probe(struct platform_device *pdev) { struct sdhci_host *host; + struct st_mmc_platform_data *pdata; struct sdhci_pltfm_host *pltfm_host; struct clk *clk; int ret = 0; u16 host_version; + struct resource *res; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; clk = devm_clk_get(&pdev->dev, "mmc"); if (IS_ERR(clk)) { @@ -162,10 +173,17 @@ static int sdhci_st_probe(struct platform_device *pdev) return PTR_ERR(clk); } + pdata->rstc = devm_reset_control_get(&pdev->dev, NULL); + if (IS_ERR(pdata->rstc)) + pdata->rstc = NULL; + else + reset_control_deassert(pdata->rstc); + host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, 0); if (IS_ERR(host)) { dev_err(&pdev->dev, "Failed sdhci_pltfm_init\n"); - return PTR_ERR(host); + ret = PTR_ERR(host); + goto err_pltfm_init; } ret = mmc_of_parse(host->mmc); @@ -176,7 +194,17 @@ static int sdhci_st_probe(struct platform_device *pdev) clk_prepare_enable(clk); + /* 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); + if (IS_ERR(pdata->top_ioaddr)) { + dev_warn(&pdev->dev, "FlashSS Top Dly registers not available"); + pdata->top_ioaddr = NULL; + } + pltfm_host = sdhci_priv(host); + pltfm_host->priv = pdata; pltfm_host->clk = clk; ret = sdhci_add_host(host); @@ -200,6 +228,9 @@ err_out: clk_disable_unprepare(clk); err_of: sdhci_pltfm_free(pdev); +err_pltfm_init: + if (pdata->rstc) + reset_control_assert(pdata->rstc); return ret; } @@ -208,10 +239,17 @@ static int 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 = pltfm_host->priv; + int ret; clk_disable_unprepare(pltfm_host->clk); - return sdhci_pltfm_unregister(pdev); + ret = sdhci_pltfm_unregister(pdev); + + if (pdata->rstc) + reset_control_assert(pdata->rstc); + + return ret; } #ifdef CONFIG_PM_SLEEP @@ -219,11 +257,15 @@ static int sdhci_st_suspend(struct device *dev) { struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct st_mmc_platform_data *pdata = pltfm_host->priv; int ret = sdhci_suspend_host(host); if (ret) goto out; + if (pdata->rstc) + reset_control_assert(pdata->rstc); + clk_disable_unprepare(pltfm_host->clk); out: return ret; @@ -233,9 +275,13 @@ static int sdhci_st_resume(struct device *dev) { struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct st_mmc_platform_data *pdata = pltfm_host->priv; clk_prepare_enable(pltfm_host->clk); + if (pdata->rstc) + reset_control_deassert(pdata->rstc); + return sdhci_resume_host(host); } #endif -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 6/8] mmc: sdhci-st: Update the quirks for this controller.
Some additional quirks need to be enabled now we support UHS modes. This avoids some spurious warnings like "Got data interrupt 0x0002 even though no data operation was in progress" Testing on stih410-b2120 board achieves the following speeds with HS200 eMMC card. max-frequency = 200Mhz /dev/mmcblk0p1: Timing buffered disk reads: 270 MB in 3.02 seconds = 89.54 MB/sec max-frequency = 100Mhz root@debian-armhf:~# hdparm -t /dev/mmcblk0p1 /dev/mmcblk0p1: Timing buffered disk reads: 210 MB in 3.00 seconds = 70.00 MB/sec max-frequency = 50Mhz root@debian-armhf:~# hdparm -t /dev/mmcblk0p1 /dev/mmcblk0p1: Timing buffered disk reads: 118 MB in 3.00 seconds = 39.28 MB/sec This is better than the 3.10 kernel which achieves 77.59 MB/sec at 200Mhz clock (same board/soc/eMMC). Signed-off-by: Peter Griffin Signed-off-by: Giuseppe Cavallaro --- drivers/mmc/host/sdhci-st.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index d53bc82..c6957b8 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c @@ -338,7 +338,10 @@ static const struct sdhci_ops sdhci_st_ops = { static const struct sdhci_pltfm_data sdhci_st_pdata = { .ops = &sdhci_st_ops, .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | - SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, + SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | + SDHCI_QUIRK_NO_HISPD_BIT, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | + SDHCI_QUIRK2_STOP_WITH_TC, }; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 5/8] mmc: sdhci-st: Add sdhci_st_set_uhs_signaling function.
To allow UHS modes to work properly we need to provide the st specific set_uhs_signaling callback function. This function differs from the generic sdhci_set_uhs_signaling callback in that we need to configure the correct delay depending on the UHS mode, and also set the V18_EN bit. Signed-off-by: Peter Griffin Signed-off-by: Giuseppe Cavallaro --- drivers/mmc/host/sdhci-st.c | 50 + 1 file changed, 50 insertions(+) diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index 11cf4e2..d53bc82 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c @@ -260,6 +260,55 @@ static int sdhci_st_set_dll_for_clock(struct sdhci_host *host) return ret; } +static void sdhci_st_set_uhs_signaling(struct sdhci_host *host, + unsigned int uhs) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct st_mmc_platform_data *pdata = pltfm_host->priv; + u16 ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); + int ret = 0; + + /* Select Bus Speed Mode for host */ + ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; + switch (uhs) { + /* +* Set V18_EN -- UHS modes do not work without this. +* does not change signaling voltage +*/ + + case MMC_TIMING_UHS_SDR12: + st_mmcss_set_static_delay(pdata->top_ioaddr); + ctrl_2 |= SDHCI_CTRL_UHS_SDR12 | SDHCI_CTRL_VDD_180; + break; + case MMC_TIMING_UHS_SDR25: + st_mmcss_set_static_delay(pdata->top_ioaddr); + ctrl_2 |= SDHCI_CTRL_UHS_SDR25 | SDHCI_CTRL_VDD_180; + break; + case MMC_TIMING_UHS_SDR50: + st_mmcss_set_static_delay(pdata->top_ioaddr); + ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180; + ret = sdhci_st_set_dll_for_clock(host); + break; + case MMC_TIMING_UHS_SDR104: + case MMC_TIMING_MMC_HS200: + st_mmcss_set_static_delay(pdata->top_ioaddr); + ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180; + ret = sdhci_st_set_dll_for_clock(host); + break; + case MMC_TIMING_UHS_DDR50: + case MMC_TIMING_MMC_DDR52: + st_mmcss_set_static_delay(pdata->top_ioaddr); + ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180; + break; + } + + if (ret) + dev_warn(mmc_dev(host->mmc), "Error setting dll for clock\n"); + + dev_dbg(mmc_dev(host->mmc), "uhs %d, ctrl_2 %04X\n", uhs, ctrl_2); + + sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); +} static u32 sdhci_st_readl(struct sdhci_host *host, int reg) { @@ -283,6 +332,7 @@ static const struct sdhci_ops sdhci_st_ops = { .set_bus_width = sdhci_set_bus_width, .read_l = sdhci_st_readl, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_st_set_uhs_signaling, }; static const struct sdhci_pltfm_data sdhci_st_pdata = { -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 3/8] mmc: sdhci-st: Add delay management functions for top registers (eMMC).
Due to the tight timing constriants in some UHS modes, it is required to have some delay management in the design. Two types of delay management are supported in the HW: - 1) Static delay management 2) Dynamic delay management NB: The delay management is only there when eMMC interface is selected. 1: Static delay management: is used to provide PVT dependent static delay on the clock/data lines to manage setup/hold requirements of the interface. The maximum delay possible is 3.25ns. These delays are PVT dependent, and thus delay values applied are not accurate and vary across provcess voltage and temperature range. Due to this these delays must not be used on the very time critical paths. 2. Dynamic delay locked loop (DLL): is used to provide dynamic delay management. The advantage of DLL is that it provides accurate & PVT indepedent delay. The DLL is used to provide delay on the loopback clock on "Read Path" to capture read data reliably. On TX path the clock on which output data is transmitted is delayed, resulting in delay of TX data. Signed-off-by: Peter Griffin Signed-off-by: Giuseppe Cavallaro --- drivers/mmc/host/sdhci-st.c | 58 + 1 file changed, 58 insertions(+) diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index 0101ae9..3443cc0 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c @@ -122,6 +122,64 @@ struct st_mmc_platform_data { ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY | \ ST_TOP_MMC_START_DLL_LOCK) +/* + * For clock speeds greater than 90MHz, we need to check that the + * DLL procedure has finished before switching to ultra-speed modes. + */ +#defineCLK_TO_CHECK_DLL_LOCK 9000 + +static inline void st_mmcss_set_static_delay(void __iomem *ioaddr) +{ + if (ioaddr) { + writel_relaxed(0x0, ioaddr + ST_TOP_MMC_DLY_CTRL); + writel_relaxed(ST_TOP_MMC_DLY_MAX, + ioaddr + ST_TOP_MMC_TX_CLK_DLY); + } +} + +static inline void st_mmcss_set_dll(void __iomem *ioaddr) +{ + if (ioaddr) { + writel_relaxed(ST_TOP_MMC_DYN_DLY_CONF, + ioaddr + ST_TOP_MMC_DLY_CTRL); + writel_relaxed(ST_TOP_MMC_TX_DLL_STEP_DLY_VALID, + ioaddr + ST_TOP_MMC_TX_DLL_STEP_DLY); + } +} + +static int st_mmcss_lock_dll(void __iomem *ioaddr) +{ + unsigned long curr, value; + unsigned long finish = jiffies + HZ; + + /* Checks if the DLL procedure is finished */ + do { + curr = jiffies; + value = readl(ioaddr + ST_MMC_STATUS_R); + if (value & 0x1) + return 0; + + cpu_relax(); + } while (!time_after_eq(curr, finish)); + + return -EBUSY; +} + +static int sdhci_st_set_dll_for_clock(struct sdhci_host *host) +{ + int ret = 0; + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct st_mmc_platform_data *pdata = pltfm_host->priv; + + if (host->clock > CLK_TO_CHECK_DLL_LOCK) { + st_mmcss_set_dll(pdata->top_ioaddr); + ret = st_mmcss_lock_dll(host->ioaddr); + } + + return ret; +} + + static u32 sdhci_st_readl(struct sdhci_host *host, int reg) { u32 ret; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 4/8] mmc: sdhci-st: Add st_mmcss_cconfig function to configure mmcss glue registers.
STiH407 family SoC's have glue registers in the flashSS subsystem which are used to configure the Arasan HC. This patch configures these glue registers according to what has been specified in the DT. Signed-off-by: Peter Griffin Signed-off-by: Giuseppe Cavallaro --- drivers/mmc/host/sdhci-st.c | 88 + 1 file changed, 88 insertions(+) diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index 3443cc0..11cf4e2 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c @@ -137,6 +137,87 @@ static inline void st_mmcss_set_static_delay(void __iomem *ioaddr) } } +/** + * st_mmcss_cconfig: configure the Arasan HC inside the flashSS. + * @np: dt device node. + * @host: sdhci host + * Description: this function is to configure the Arasan host controller. + * On some ST SoCs, i.e. STiH407 family, the MMC devices inside a dedicated + * flashSS sub-system which needs to be configured to be compliant to eMMC 4.5 + * or eMMC4.3. This has to be done before registering the sdhci host. + */ +static void st_mmcss_cconfig(struct device_node *np, struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct mmc_host *mhost = host->mmc; + u32 cconf2, cconf3, cconf4, cconf5; + + if (!of_device_is_compatible(np, "st,sdhci-stih407")) + return; + + cconf2 = ST_MMC_CCONFIG_2_DEFAULT; + cconf3 = ST_MMC_CCONFIG_3_DEFAULT; + cconf4 = ST_MMC_CCONFIG_4_DEFAULT; + cconf5 = ST_MMC_CCONFIG_5_DEFAULT; + + writel_relaxed(ST_MMC_CCONFIG_1_DEFAULT, + host->ioaddr + ST_MMC_CCONFIG_REG_1); + + /* Set clock frequency, default to 50MHz if max-frequency is not +* provided */ + + switch (mhost->f_max) { + case 2: + clk_set_rate(pltfm_host->clk, mhost->f_max); + cconf2 |= BASE_CLK_FREQ_200; + break; + case 1: + clk_set_rate(pltfm_host->clk, mhost->f_max); + cconf2 |= BASE_CLK_FREQ_100; + break; + default: + clk_set_rate(pltfm_host->clk, 5000); + cconf2 |= BASE_CLK_FREQ_50; + } + + writel_relaxed(cconf2, host->ioaddr + ST_MMC_CCONFIG_REG_2); + + if (mhost->caps & MMC_CAP_NONREMOVABLE) + cconf3 |= ST_MMC_CCONFIG_EMMC_SLOT_TYPE; + else + /* CARD _D ET_CTRL */ + writel_relaxed(ST_MMC_GP_OUTPUT_CD, + host->ioaddr + ST_MMC_GP_OUTPUT); + + if (mhost->caps & MMC_CAP_UHS_SDR50) { + /* use 1.8V */ + cconf3 |= ST_MMC_CCONFIG_1P8_VOLT; + cconf4 |= ST_MMC_CCONFIG_SDR50; + /* Use tuning */ + cconf5 |= ST_MMC_CCONFIG_TUNING_FOR_SDR50; + /* Max timeout for retuning */ + cconf5 |= RETUNING_TIMER_CNT_MAX; + } + + if (mhost->caps & MMC_CAP_UHS_SDR104) { + /* +* SDR104 implies the HC can support HS200 mode, so +* it's mandatory to use 1.8V +*/ + cconf3 |= ST_MMC_CCONFIG_1P8_VOLT; + cconf4 |= ST_MMC_CCONFIG_SDR104; + /* Max timeout for retuning */ + cconf5 |= RETUNING_TIMER_CNT_MAX; + } + + if (mhost->caps & MMC_CAP_UHS_DDR50) + cconf4 |= ST_MMC_CCONFIG_DDR50; + + writel_relaxed(cconf3, host->ioaddr + ST_MMC_CCONFIG_REG_3); + writel_relaxed(cconf4, host->ioaddr + ST_MMC_CCONFIG_REG_4); + writel_relaxed(cconf5, host->ioaddr + ST_MMC_CCONFIG_REG_5); +} + static inline void st_mmcss_set_dll(void __iomem *ioaddr) { if (ioaddr) { @@ -213,6 +294,7 @@ static const struct sdhci_pltfm_data sdhci_st_pdata = { static int sdhci_st_probe(struct platform_device *pdev) { + struct device_node *np = pdev->dev.of_node; struct sdhci_host *host; struct st_mmc_platform_data *pdata; struct sdhci_pltfm_host *pltfm_host; @@ -265,6 +347,9 @@ static int sdhci_st_probe(struct platform_device *pdev) pltfm_host->priv = pdata; pltfm_host->clk = clk; + /* Configure the Arasan HC inside the flashSS */ + st_mmcss_cconfig(np, host); + ret = sdhci_add_host(host); if (ret) { dev_err(&pdev->dev, "Failed sdhci_add_host\n"); @@ -334,12 +419,15 @@ static int sdhci_st_resume(struct device *dev) struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct st_mmc_platform_data *pdata = pltfm_host->priv; + struct device_node *np = dev->of_node; clk_prepare_enable(pltfm_host->clk); if (pdata->rstc) reset_control_deassert(pdata->rstc); + st_mmcss_cconfig(np, host); + return sdhci_resume_host(host); } #endif -- 1.9.1 -- To unsubscr
[PATCH v2 8/8] ARM: STi: DT: STiH407: Add dt nodes for sdhci and emmc.
The nodes have been split to allow as much commonality as possible. The stih407 has a silicon bug with eMMC UHS modes (with top regs) and as such doesn't have any of the uhs dt properties. Signed-off-by: Peter Griffin --- arch/arm/boot/dts/stih407-family.dtsi | 30 ++ arch/arm/boot/dts/stih410-b2120.dts | 10 ++ arch/arm/boot/dts/stihxxx-b2120.dtsi | 8 3 files changed, 48 insertions(+) diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi index c06a546..77614a5 100644 --- a/arch/arm/boot/dts/stih407-family.dtsi +++ b/arch/arm/boot/dts/stih407-family.dtsi @@ -336,5 +336,35 @@ resets = <&softreset STIH407_MIPHY2_SOFTRESET>; }; }; + + mmc0: sdhci@0906 { + compatible = "st,sdhci-stih407", "st,sdhci"; + status = "disabled"; + reg = <0x0906 0x7ff>, <0x9061008 0x20>; + reg-names = "mmc", "top-mmc-delay"; + interrupts = ; + interrupt-names = "mmcirq"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mmc0>; + clock-names = "mmc"; + clocks = <&clk_s_c0_flexgen CLK_MMC_0>; + bus-width = <8>; + non-removable; + }; + + mmc1: sdhci@0908 { + compatible = "st,sdhci-stih407", "st,sdhci"; + status = "disabled"; + reg = <0x0908 0x7ff>; + reg-names = "mmc"; + interrupts = ; + interrupt-names = "mmcirq"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sd1>; + clock-names = "mmc"; + clocks = <&clk_s_c0_flexgen CLK_MMC_1>; + resets = <&softreset STIH407_MMC1_SOFTRESET>; + bus-width = <4>; + }; }; }; diff --git a/arch/arm/boot/dts/stih410-b2120.dts b/arch/arm/boot/dts/stih410-b2120.dts index 2f61a99..16f02c5 100644 --- a/arch/arm/boot/dts/stih410-b2120.dts +++ b/arch/arm/boot/dts/stih410-b2120.dts @@ -26,4 +26,14 @@ aliases { ttyAS0 = &sbc_serial0; }; + + soc { + + mmc0: sdhci@0906 { + max-frequency = <2>; + sd-uhs-sdr50; + sd-uhs-sdr104; + sd-uhs-ddr50; + }; + }; }; diff --git a/arch/arm/boot/dts/stihxxx-b2120.dtsi b/arch/arm/boot/dts/stihxxx-b2120.dtsi index c1d8590..64fa0b5 100644 --- a/arch/arm/boot/dts/stihxxx-b2120.dtsi +++ b/arch/arm/boot/dts/stihxxx-b2120.dtsi @@ -47,6 +47,14 @@ status = "okay"; }; + mmc0: sdhci@0906 { + status = "okay"; + }; + + mmc1: sdhci@0908 { + status = "okay"; + }; + /* SSC11 to HDMI */ hdmiddc: i2c@9541000 { status = "okay"; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] mmc: card: not access RPMB partition for normal read and write
On Wed, Oct 01, 2014 at 05:53:30PM +0400, I wrote: > what is the status of this patch to cope with MMC RPMB? > http://permalink.gmane.org/gmane.linux.kernel.mmc/28281 Just in case, it's now also Tested-by: Michael Shigorin Hope to see this merged! 2 debian: please note that udev rules fixup is required, see also https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/1333140 -- it's been fixed in 219 or see the patch in 218-10ubuntu1 package. -- WBR, Michael Shigorin / http://altlinux.org -- http://opennet.ru / http://anna-news.info From: Martin Pitt Date: Wed, 11 Feb 2015 15:26:52 +0100 Subject: rules: Fix by-path of mmc RPMB partitions and don't blkid them Linux 3.10+ exposes RPMB (Replay Protected Memory Block) partitions of MMC devices [1] ; trying to read them with blkid or other unspecific means will cause kernel buffer I/O errors and timeouts. Blacklist those to prevent creating wrong by-path links and blkid'ing those. [1] http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=090d25fe224c0 https://launchpad.net/bugs/1333140 --- rules/60-persistent-storage.rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/60-persistent-storage.rules b/rules/60-persistent-storage.rules index 475b151..25b44a5 100644 --- a/rules/60-persistent-storage.rules +++ b/rules/60-persistent-storage.rules @@ -14,7 +14,7 @@ ACTION=="add", SUBSYSTEM=="module", KERNEL=="block", ATTR{parameters/events_dfl_ SUBSYSTEM!="block", GOTO="persistent_storage_end" # skip rules for inappropriate block devices -KERNEL=="fd*|mtd*|nbd*|gnbd*|btibm*|dm-*|md*|zram*", GOTO="persistent_storage_end" +KERNEL=="fd*|mtd*|nbd*|gnbd*|btibm*|dm-*|md*|zram*|mmcblk[0-9]*rpmb", GOTO="persistent_storage_end" # ignore partitions that span the entire disk TEST=="whole_disk", GOTO="persistent_storage_end"
[PATCH v2 09/11] mmc: kconfig: replace PPC_OF with PPC
The PPC_OF is a ppc specific option which is used to mean that the firmware device tree access functions are available. Since all the ppc platforms have a device tree, it is aways set to 'y' for ppc. So it makes no sense to keep a such option in the current kernel. Replace it with PPC. Signed-off-by: Kevin Hao --- v2: No change. drivers/mmc/host/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 61ac63a3776a..7858d7a52818 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -132,7 +132,7 @@ config MMC_SDHCI_OF_ARASAN config MMC_SDHCI_OF_ESDHC tristate "SDHCI OF support for the Freescale eSDHC controller" depends on MMC_SDHCI_PLTFM - depends on PPC_OF + depends on PPC select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER help This selects the Freescale eSDHC controller support. @@ -144,7 +144,7 @@ config MMC_SDHCI_OF_ESDHC config MMC_SDHCI_OF_HLWD tristate "SDHCI OF support for the Nintendo Wii SDHCI controllers" depends on MMC_SDHCI_PLTFM - depends on PPC_OF + depends on PPC select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER help This selects the Secure Digital Host Controller Interface (SDHCI) -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 00/11] powerpc: kill PPC_OF
Hi, v2: - Drop the following patches which were already merged. be802bf955a1 ("mtd: kconfig: replace PPC_OF with PPC") 0a4a3529df40 ("gpio: kconfig: replace PPC_OF with PPC") c31316cb6c5a ("usb: kconfig: replace PPC_OF with PPC") f0b66a2cf68e ("PCI: Add pci_device_to_OF_node() stub for !CONFIG_OF") - Add the ack in v1 cycle. - Resolve the comments in v1 cycle. We plan to merge this patch series via the powerpc tree in 4.1 cycle. So please ack the corresponding patches if you are OK with these changes. Kevin Hao (11): sata_svw: remove the dependency on PPC_OF fbdev: aty128fb: replace PPC_OF with PPC fbdev: radeon: replace PPC_OF with PPC fbdev: imsttfb: remove the dependency on PPC_OF fbdev: nvidia: remove the dependency on PPC_OF fbdev: riva: remove the dependency on PPC_OF fbdev: remove the unnecessary includes of ppc specific header files fbdev: kconfig: replace PPC_OF with PPC mmc: kconfig: replace PPC_OF with PPC tty: kconfig: remove the superfluous dependency on PPC_OF powerpc: kill PPC_OF arch/powerpc/Kconfig | 3 --- arch/powerpc/Kconfig.debug | 2 +- arch/powerpc/kernel/Makefile | 4 ++-- drivers/ata/sata_svw.c | 11 +-- drivers/mmc/host/Kconfig | 4 ++-- drivers/tty/serial/Kconfig | 4 ++-- drivers/video/fbdev/Kconfig | 4 ++-- drivers/video/fbdev/aty/aty128fb.c | 4 ++-- drivers/video/fbdev/aty/radeon_base.c| 24 drivers/video/fbdev/aty/radeon_monitor.c | 20 ++-- drivers/video/fbdev/aty/radeon_pm.c | 16 drivers/video/fbdev/aty/radeonfb.h | 4 ++-- drivers/video/fbdev/core/fbmon.c | 4 drivers/video/fbdev/imsttfb.c| 6 +- drivers/video/fbdev/nvidia/Makefile | 3 +-- drivers/video/fbdev/nvidia/nv_of.c | 3 --- drivers/video/fbdev/nvidia/nv_proto.h| 8 drivers/video/fbdev/nvidia/nvidia.c | 4 drivers/video/fbdev/riva/fbdev.c | 17 +++-- 19 files changed, 53 insertions(+), 92 deletions(-) -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RT PATCH] mmc: sdhci: don't provide hard irq handler
the sdhci code provides both irq handlers: the primary and the thread handler. Initially it was meant for the primary handler to be very short. The result is not that on -RT we have the primrary handler grabing locks and this isn't really working. As a hack for now I just push both handler into the threaded mode. Reported-By: Michal Šmucr Signed-off-by: Sebastian Andrzej Siewior --- The "same thing" was reported against the iwlwifi driver (request_threaded_irq(…, iwl_pcie_isr, iwl_pcie_irq_handler, …) and they managed to rework it and not do anything that would break -RT in their primary handler. Besides sdhci there are a few others drivers in the same tree doing similar things. I'm not sure what to do here in general. Motivating upstream maintainer to rework their code or introducing IRQF_RT_SAFE and for others doing the conversation like in the patch below. Michal: This is untested but should fix the issue, reported. drivers/mmc/host/sdhci.c | 32 +++- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 023c2010cd75..bcde53774bc9 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2565,6 +2565,31 @@ static irqreturn_t sdhci_thread_irq(int irq, void *dev_id) return isr ? IRQ_HANDLED : IRQ_NONE; } +#ifdef CONFIG_PREEMPT_RT_BASE +static irqreturn_t sdhci_rt_irq(int irq, void *dev_id) +{ + irqreturn_t ret; + + local_bh_disable(); + ret = sdhci_irq(irq, dev_id); + local_bh_enable(); + if (ret == IRQ_WAKE_THREAD) + ret = sdhci_thread_irq(irq, dev_id); + return ret; +} +#endif + +static int sdhci_req_irq(struct sdhci_host *host) +{ +#ifdef CONFIG_PREEMPT_RT_BASE + return request_threaded_irq(host->irq, NULL, sdhci_rt_irq, + IRQF_SHARED, mmc_hostname(host->mmc), host); +#else + return request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq, + IRQF_SHARED, mmc_hostname(host->mmc), host); +#endif +} + /*\ * * * Suspend/resume* @@ -2632,9 +2657,7 @@ int sdhci_resume_host(struct sdhci_host *host) } if (!device_may_wakeup(mmc_dev(host->mmc))) { - ret = request_threaded_irq(host->irq, sdhci_irq, - sdhci_thread_irq, IRQF_SHARED, - mmc_hostname(host->mmc), host); + ret = sdhci_req_irq(host); if (ret) return ret; } else { @@ -3253,8 +3276,7 @@ int sdhci_add_host(struct sdhci_host *host) sdhci_init(host, 0); - ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq, - IRQF_SHARED, mmc_hostname(mmc), host); + ret = sdhci_req_irq(host); if (ret) { pr_err("%s: Failed to request IRQ %d: %d\n", mmc_hostname(mmc), host->irq, ret); -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html