mmc: sdhci-omap: Workaround for Errata i843
authorKishon Vijay Abraham I <kishon@ti.com>
Fri, 27 Apr 2018 11:47:12 +0000 (17:17 +0530)
committerUlf Hansson <ulf.hansson@linaro.org>
Thu, 3 May 2018 07:35:21 +0000 (09:35 +0200)
Errata i843 in AM572x Sitara Processors Silicon Revision 2.0, 1.1
(SPRZ429K July 2014–Revised March 2017 [1]) mentions
PG 1.0/1.1 silicon has limitations w.r.t frequencies at which MMC1/2/3
can operate.

Use soc_device_match() to identify rev 1.0/1.1 silicon and
override mmc->f_max according to the errata workaround.
"max-frequency" dt property cannot be used since the device
tree is added for rev 2.0 silicon.

soc_device_match() is also used in order to get the IODelay values
for rev 1.0/1.1 silicon.

[1] -> http://www.ti.com/lit/er/sprz429k/sprz429k.pdf

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/host/sdhci-omap.c

index 78f3ceea570eec5cdf514834c1be9fd3cfcf233d..b3dc7f1466e5680eb6c4c0ae185afc600e3bf40a 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/sys_soc.h>
 
 #include "sdhci-pltfm.h"
 
@@ -100,6 +101,7 @@ struct sdhci_omap_data {
 };
 
 struct sdhci_omap_host {
+       char                    *version;
        void __iomem            *base;
        struct device           *dev;
        struct  regulator       *pbias;
@@ -733,12 +735,21 @@ static struct pinctrl_state
                                  u32 *caps, u32 capmask)
 {
        struct device *dev = omap_host->dev;
+       char *version = omap_host->version;
        struct pinctrl_state *pinctrl_state = ERR_PTR(-ENODEV);
+       char str[20];
 
        if (!(*caps & capmask))
                goto ret;
 
-       pinctrl_state = pinctrl_lookup_state(omap_host->pinctrl, mode);
+       if (version) {
+               snprintf(str, 20, "%s-%s", mode, version);
+               pinctrl_state = pinctrl_lookup_state(omap_host->pinctrl, str);
+       }
+
+       if (IS_ERR(pinctrl_state))
+               pinctrl_state = pinctrl_lookup_state(omap_host->pinctrl, mode);
+
        if (IS_ERR(pinctrl_state)) {
                dev_err(dev, "no pinctrl state for %s mode", mode);
                *caps &= ~capmask;
@@ -830,6 +841,16 @@ static int sdhci_omap_config_iodelay_pinctrl_state(struct sdhci_omap_host
        return 0;
 }
 
+static const struct soc_device_attribute sdhci_omap_soc_devices[] = {
+       {
+               .machine = "DRA7[45]*",
+               .revision = "ES1.[01]",
+       },
+       {
+               /* sentinel */
+       }
+};
+
 static int sdhci_omap_probe(struct platform_device *pdev)
 {
        int ret;
@@ -841,6 +862,7 @@ static int sdhci_omap_probe(struct platform_device *pdev)
        struct mmc_host *mmc;
        const struct of_device_id *match;
        struct sdhci_omap_data *data;
+       const struct soc_device_attribute *soc;
 
        match = of_match_device(omap_sdhci_match, dev);
        if (!match)
@@ -875,6 +897,17 @@ static int sdhci_omap_probe(struct platform_device *pdev)
        if (ret)
                goto err_pltfm_free;
 
+       soc = soc_device_match(sdhci_omap_soc_devices);
+       if (soc) {
+               omap_host->version = "rev11";
+               if (!strcmp(dev_name(dev), "4809c000.mmc"))
+                       mmc->f_max = 96000000;
+               if (!strcmp(dev_name(dev), "480b4000.mmc"))
+                       mmc->f_max = 48000000;
+               if (!strcmp(dev_name(dev), "480ad000.mmc"))
+                       mmc->f_max = 48000000;
+       }
+
        pltfm_host->clk = devm_clk_get(dev, "fck");
        if (IS_ERR(pltfm_host->clk)) {
                ret = PTR_ERR(pltfm_host->clk);