mmc: sdhci-omap: Workaround for Errata i843

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>
This commit is contained in:
Kishon Vijay Abraham I 2018-04-27 17:17:12 +05:30 коммит произвёл Ulf Hansson
Родитель 5bc2bda54d
Коммит 212f4f8a44
1 изменённых файлов: 34 добавлений и 1 удалений

Просмотреть файл

@ -26,6 +26,7 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/sys_soc.h>
#include "sdhci-pltfm.h" #include "sdhci-pltfm.h"
@ -100,6 +101,7 @@ struct sdhci_omap_data {
}; };
struct sdhci_omap_host { struct sdhci_omap_host {
char *version;
void __iomem *base; void __iomem *base;
struct device *dev; struct device *dev;
struct regulator *pbias; struct regulator *pbias;
@ -733,12 +735,21 @@ static struct pinctrl_state
u32 *caps, u32 capmask) u32 *caps, u32 capmask)
{ {
struct device *dev = omap_host->dev; struct device *dev = omap_host->dev;
char *version = omap_host->version;
struct pinctrl_state *pinctrl_state = ERR_PTR(-ENODEV); struct pinctrl_state *pinctrl_state = ERR_PTR(-ENODEV);
char str[20];
if (!(*caps & capmask)) if (!(*caps & capmask))
goto ret; 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)) { if (IS_ERR(pinctrl_state)) {
dev_err(dev, "no pinctrl state for %s mode", mode); dev_err(dev, "no pinctrl state for %s mode", mode);
*caps &= ~capmask; *caps &= ~capmask;
@ -830,6 +841,16 @@ static int sdhci_omap_config_iodelay_pinctrl_state(struct sdhci_omap_host
return 0; 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) static int sdhci_omap_probe(struct platform_device *pdev)
{ {
int ret; int ret;
@ -841,6 +862,7 @@ static int sdhci_omap_probe(struct platform_device *pdev)
struct mmc_host *mmc; struct mmc_host *mmc;
const struct of_device_id *match; const struct of_device_id *match;
struct sdhci_omap_data *data; struct sdhci_omap_data *data;
const struct soc_device_attribute *soc;
match = of_match_device(omap_sdhci_match, dev); match = of_match_device(omap_sdhci_match, dev);
if (!match) if (!match)
@ -875,6 +897,17 @@ static int sdhci_omap_probe(struct platform_device *pdev)
if (ret) if (ret)
goto err_pltfm_free; 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"); pltfm_host->clk = devm_clk_get(dev, "fck");
if (IS_ERR(pltfm_host->clk)) { if (IS_ERR(pltfm_host->clk)) {
ret = PTR_ERR(pltfm_host->clk); ret = PTR_ERR(pltfm_host->clk);