mmc: omap_hsmmc: Add support to get pinctrl values and max frequency for different hw revisions

AM572x SR1.1 requires different IODelay values to be used than that used
in AM572x SR2.0. These values are populated in device tree. Add
capability in omap_hsmmc driver to extract IOdelay values for different
silicon revision. The maximum frequency is also reduced when using a ES1.1.
To keep the ability to boot both revsions with the same dtb, those values
can be provided by the platform code.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
diff --git a/arch/arm/include/asm/arch-omap5/sys_proto.h b/arch/arm/include/asm/arch-omap5/sys_proto.h
index a6b3557..d43cd7f 100644
--- a/arch/arm/include/asm/arch-omap5/sys_proto.h
+++ b/arch/arm/include/asm/arch-omap5/sys_proto.h
@@ -35,6 +35,12 @@
 	u32 val;
 };
 
+struct mmc_platform_fixups {
+	const char *hw_rev;
+	u32 unsupported_caps;
+	u32 max_freq;
+};
+
 struct omap_sysinfo {
 	char *board_string;
 };
@@ -71,6 +77,7 @@
 void get_ioregs(const struct ctrl_ioregs **regs);
 void srcomp_enable(void);
 void setup_warmreset_time(void);
+const struct mmc_platform_fixups *platform_fixups_mmc(uint32_t addr);
 
 static inline u32 div_round_up(u32 num, u32 den)
 {
diff --git a/arch/arm/include/asm/omap_mmc.h b/arch/arm/include/asm/omap_mmc.h
index 635ce1e..c50087e 100644
--- a/arch/arm/include/asm/omap_mmc.h
+++ b/arch/arm/include/asm/omap_mmc.h
@@ -70,6 +70,7 @@
 	struct mmc mmc;
 	bool cd_inverted;
 	u32 controller_flags;
+	const char *hw_rev;
 };
 
 /*
diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c
index 2b77422..766cd09 100644
--- a/drivers/mmc/omap_hsmmc.c
+++ b/drivers/mmc/omap_hsmmc.c
@@ -96,6 +96,7 @@
 	struct omap_hsmmc_adma_desc *adma_desc_table;
 	uint desc_slot;
 #endif
+	const char *hw_rev;
 #ifdef CONFIG_IODELAY_RECALIBRATION
 	struct omap_hsmmc_pinctrl_state *default_pinctrl_state;
 	struct omap_hsmmc_pinctrl_state *hs_pinctrl_state;
@@ -1368,6 +1369,7 @@
 	if ((get_cpu_family() == CPU_OMAP34XX) && (get_cpu_rev() <= CPU_3XX_ES21))
 		cfg->b_max = 1;
 #endif
+
 	mmc = mmc_create(cfg, priv);
 	if (mmc == NULL)
 		return -1;
@@ -1587,20 +1589,28 @@
 	return 0;
 }
 
-#define OMAP_HSMMC_SETUP_PINCTRL(capmask, mode)			\
-	do {							\
-		struct omap_hsmmc_pinctrl_state *s;		\
-		if (!(cfg->host_caps & capmask))		\
-			break;					\
-								\
-		s = omap_hsmmc_get_pinctrl_by_mode(mmc, #mode);	\
-		if (!s) {					\
-			debug("%s: no pinctrl for %s\n",	\
-			      mmc->dev->name, #mode);		\
-			cfg->host_caps &= ~(capmask);		\
-		} else {					\
-			priv->mode##_pinctrl_state = s;		\
-		}						\
+#define OMAP_HSMMC_SETUP_PINCTRL(capmask, mode)				\
+	do {								\
+		struct omap_hsmmc_pinctrl_state *s = NULL;		\
+		char str[20];						\
+		if (!(cfg->host_caps & capmask))			\
+			break;						\
+									\
+		if (priv->hw_rev) {					\
+			sprintf(str, "%s-%s", #mode, priv->hw_rev);	\
+			s = omap_hsmmc_get_pinctrl_by_mode(mmc, str);	\
+		}							\
+									\
+		if (!s)							\
+			s = omap_hsmmc_get_pinctrl_by_mode(mmc, #mode);	\
+									\
+		if (!s) {						\
+			debug("%s: no pinctrl for %s\n",		\
+			      mmc->dev->name, #mode);			\
+			cfg->host_caps &= ~(capmask);			\
+		} else {						\
+			priv->mode##_pinctrl_state = s;			\
+		}							\
 	} while (0)
 
 static int omap_hsmmc_get_pinctrl_state(struct mmc *mmc)
@@ -1635,12 +1645,22 @@
 #endif
 
 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+#ifdef CONFIG_OMAP54XX
+__weak const struct mmc_platform_fixups *platform_fixups_mmc(uint32_t addr)
+{
+	return NULL;
+}
+#endif
+
 static int omap_hsmmc_ofdata_to_platdata(struct udevice *dev)
 {
 	struct omap_hsmmc_plat *plat = dev_get_platdata(dev);
 	struct omap_mmc_of_data *of_data = (void *)dev_get_driver_data(dev);
 
 	struct mmc_config *cfg = &plat->cfg;
+#ifdef CONFIG_OMAP54XX
+	const struct mmc_platform_fixups *fixups;
+#endif
 	const void *fdt = gd->fdt_blob;
 	int node = dev_of_offset(dev);
 	int ret;
@@ -1664,6 +1684,15 @@
 	if (of_data)
 		plat->controller_flags |= of_data->controller_flags;
 
+#ifdef CONFIG_OMAP54XX
+	fixups = platform_fixups_mmc(devfdt_get_addr(dev));
+	if (fixups) {
+		plat->hw_rev = fixups->hw_rev;
+		cfg->host_caps &= ~fixups->unsupported_caps;
+		cfg->f_max = fixups->max_freq;
+	}
+#endif
+
 #ifdef OMAP_HSMMC_USE_GPIO
 	plat->cd_inverted = fdtdec_get_bool(fdt, node, "cd-inverted");
 #endif
@@ -1695,6 +1724,7 @@
 	cfg->name = "OMAP SD/MMC";
 	priv->base_addr = plat->base_addr;
 	priv->controller_flags = plat->controller_flags;
+	priv->hw_rev = plat->hw_rev;
 #ifdef OMAP_HSMMC_USE_GPIO
 	priv->cd_inverted = plat->cd_inverted;
 #endif