diff mbox

sdhci-s3c: support non-standard clock setting for c210

Message ID 4C7CDA39.1020907@samsung.com (mailing list archive)
State Awaiting Upstream, archived
Headers show

Commit Message

Jaehoon Chung Aug. 31, 2010, 10:32 a.m. UTC
None
diff mbox

Patch

diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h
index 30844c2..7c75ee3 100644
--- a/arch/arm/plat-samsung/include/plat/sdhci.h
+++ b/arch/arm/plat-samsung/include/plat/sdhci.h
@@ -15,6 +15,8 @@ 
 #ifndef __PLAT_S3C_SDHCI_H
 #define __PLAT_S3C_SDHCI_H __FILE__
 
+#include <plat/devs.h>
+
 struct platform_device;
 struct mmc_host;
 struct mmc_card;
@@ -288,4 +290,21 @@  static inline void s5pv210_default_sdhci3(void) { }
 
 #endif /* CONFIG_S5PV210_SETUP_SDHCI */
 
+/* re-define device name depending on support. */
+static inline void s3c_hsmmc_setname(char *name)
+{
+#ifdef CONFIG_S3C_DEV_HSMMC
+	s3c_device_hsmmc0.name = name;
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC1
+	s3c_device_hsmmc1.name = name;
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC2
+	s3c_device_hsmmc2.name = name;
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC3
+	s3c_device_hsmmc3.name = name;
+#endif
+}
+
 #endif /* __PLAT_S3C_SDHCI_H */
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 71ad416..3927793 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -52,6 +52,11 @@  struct sdhci_s3c {
 	struct clk		*clk_bus[MAX_BUS_CLK];
 };
 
+enum soc_type {
+	TYPE_SAMSUNG,	/* S5PC1XX, S3C... */
+	TYPE_S5PC210,	/* S5PC210 */
+};
+
 static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
 {
 	return sdhci_priv(host);
@@ -232,6 +237,52 @@  static unsigned int sdhci_s3c_get_min_clock(struct sdhci_host *host)
 	return min;
 }
 
+/**
+* sdhci_s3c_get_max_clk - callback to get maximum clock frequency.
+*/
+static unsigned int sdhci_s5pc210_get_max_clock(struct sdhci_host *host)
+{
+	struct sdhci_s3c *ourhost = to_s3c(host);
+	unsigned int rate;
+	int ptr = ourhost->cur_clk;
+
+	rate = clk_round_rate(ourhost->clk_bus[ptr], UINT_MAX);
+
+	return rate;
+}
+
+/**
+ * sdhci_s3c_get_min_clock - callback to get minimal supported clock value
+*/
+static unsigned int sdhci_s5pc210_get_min_clock(struct sdhci_host *host)
+{
+	struct sdhci_s3c *ourhost = to_s3c(host);
+	unsigned int rate;
+	int ptr = ourhost->cur_clk;
+
+	rate = clk_round_rate(ourhost->clk_bus[ptr], 400000);
+
+	return rate;
+}
+
+/**
+ * sdhci_s5pc210_set_clock - callback on clock change
+*/
+static void sdhci_s5pc210_set_clock(struct sdhci_host *host,
+		unsigned int clock)
+{
+	struct sdhci_s3c *ourhost = to_s3c(host);
+
+	if (clock == 0)
+		return;
+
+	sdhci_s3c_set_clock(host, clock);
+
+	clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock);
+
+	host->clock = clock;
+}
+
 static struct sdhci_ops sdhci_s3c_ops = {
 	.get_max_clock		= sdhci_s3c_get_max_clk,
 	.set_clock		= sdhci_s3c_set_clock,
@@ -395,6 +446,12 @@  static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
 	host->quirks = 0;
 	host->irq = irq;
 
+	if (pdev->id_entry->driver_data == TYPE_S5PC210) {
+		sdhci_s3c_ops.set_clock = sdhci_s5pc210_set_clock;
+		sdhci_s3c_ops.get_min_clock = sdhci_s5pc210_get_min_clock;
+		sdhci_s3c_ops.get_max_clock = sdhci_s5pc210_get_max_clock;
+	}
+
 	/* Setup quirks for the controller */
 	host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
 	host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
@@ -520,6 +577,16 @@  static int sdhci_s3c_resume(struct platform_device *dev)
 #define sdhci_s3c_resume NULL
 #endif
 
+static struct platform_device_id sdhci_driver_ids[] = {
+	{
+		.name		= "s3c-sdhci",
+		.driver_data	= TYPE_SAMSUNG,
+	}, {
+		.name		= "s5pc210-sdhci",
+		.driver_data	= TYPE_S5PC210,
+	}, { },
+};
+
 static struct platform_driver sdhci_s3c_driver = {
 	.probe		= sdhci_s3c_probe,
 	.remove		= __devexit_p(sdhci_s3c_remove),
@@ -529,6 +596,7 @@  static struct platform_driver sdhci_s3c_driver = {
 		.owner	= THIS_MODULE,
 		.name	= "s3c-sdhci",
 	},
+	.id_table	= sdhci_driver_ids,
 };
 
 static int __init sdhci_s3c_init(void)