linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] mmc: sdhci-s3c: Remove 'clk_type' member from platform data
@ 2011-10-04  7:28 Thomas Abraham
  2011-10-04  7:28 ` [PATCH 1/3] mmc: sdhci-s3c: Remove usage of clk_type member in " Thomas Abraham
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Thomas Abraham @ 2011-10-04  7:28 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset removes all uses of 'clk_type' member from the platform data
of sdhci-s3c driver. The clk_type is a SoC specific information and not a board/
machine specific information. Hence, this information can be more aptly
represented using SoC specific driver data in the sdhci-s3c driver.

Hence all uses of 'clk_type' member in sdhci-s3c driver's platform data is
removed. In place of that, the sdhci host qurik 'SDHCI_QUIRK_NONSTANDARD_CLOCK'
is used to handle controllers that do not have a standard sdclk division
(like those in the exynos4 SoC's).

This is a pre-requisite patchset for adding device tree support for sdhci-s3c
driver. While migrating towards device tree support, retreving 'clk_type'
information does not seem correct and hence it has been added as SoC specific
driver data.

This patchset is based on the following tree
https://github.com/kgene/linux-samsung.git  branch: for-next

and tested on smdkv310, smdkv210 and smdk2416.

Thomas Abraham (3):
  mmc: sdhci-s3c: Remove usage of clk_type member in platform data
  arm: exynos4: use 'exynos4-sdhci' as device name for sdhci controllers
  arm: samsung: remove all uses of clk_type member in sdhci platform data

 arch/arm/mach-exynos4/clock.c               |   16 +++---
 arch/arm/mach-exynos4/cpu.c                 |    5 ++
 arch/arm/mach-exynos4/mach-armlex4210.c     |    3 -
 arch/arm/mach-exynos4/mach-nuri.c           |    3 -
 arch/arm/mach-exynos4/mach-origen.c         |    2 -
 arch/arm/mach-exynos4/mach-smdk4212.c       |    2 -
 arch/arm/mach-exynos4/mach-smdkv310.c       |    4 --
 arch/arm/mach-exynos4/mach-universal_c210.c |    2 -
 arch/arm/plat-samsung/dev-hsmmc.c           |    1 -
 arch/arm/plat-samsung/dev-hsmmc1.c          |    1 -
 arch/arm/plat-samsung/dev-hsmmc2.c          |    1 -
 arch/arm/plat-samsung/dev-hsmmc3.c          |    1 -
 arch/arm/plat-samsung/include/plat/sdhci.h  |   34 ++++++++++---
 arch/arm/plat-samsung/platformdata.c        |    2 -
 drivers/mmc/host/sdhci-s3c.c                |   74 +++++++++++++++++++++++++--
 15 files changed, 110 insertions(+), 41 deletions(-)

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/3] mmc: sdhci-s3c: Remove usage of clk_type member in platform data
  2011-10-04  7:28 [PATCH 0/3] mmc: sdhci-s3c: Remove 'clk_type' member from platform data Thomas Abraham
@ 2011-10-04  7:28 ` Thomas Abraham
  2011-10-04  7:53   ` Kyungmin Park
  2011-10-04  7:28 ` [PATCH 2/3] arm: exynos4: use 'exynos4-sdhci' as device name for sdhci controllers Thomas Abraham
  2011-10-04  7:28 ` [PATCH 3/3] arm: samsung: remove all uses of clk_type member in sdhci platform data Thomas Abraham
  2 siblings, 1 reply; 6+ messages in thread
From: Thomas Abraham @ 2011-10-04  7:28 UTC (permalink / raw)
  To: linux-arm-kernel

SDHCI controllers on Exynos4 do not include the sdclk divider as per the
sdhci controller specification. This case can be represented using the
sdhci quirk SDHCI_QUIRK_NONSTANDARD_CLOCK instead of using an additional
enum type definition 'clk_types'.

Hence, usage of clk_type member in platform data is removed and the sdhci
quirk is used. In addition to that, since this qurik is SoC specific,
driver data is introduced to represent controllers on SoC's that require
this quirk.

Cc: Ben Dooks <ben-linux@fluff.org>
Cc: Jeongbae Seo <jeongbae.seo@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
In the function 'sdhci_cmu_set_clock', the code that waits for a stable
sdclk clock is replicated from 'sdhci_set_clock' function. This portion
of code is replicated in sdhci-cns3xxx driver as well. This duplication
could have been avoid by adding a new function in sdhci host controller
driver that waits for stable sdclk and sdhci-s3c/sdhci-cns3xxx can be
the users of the new function. If adding a new function in sdhci host
controller driver is acceptable, an additional patch in this series
can be added that creates the new function that waits for stable sdclk.

 drivers/mmc/host/sdhci-s3c.c |   74 +++++++++++++++++++++++++++++++++++++++--
 1 files changed, 70 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 82709b6..b29e734 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -53,6 +53,18 @@ struct sdhci_s3c {
 	struct clk		*clk_bus[MAX_BUS_CLK];
 };
 
+/**
+ * struct sdhci_s3c_driver_data - S3C SDHCI platform specific driver data
+ * @sdhci_quirks: sdhci host specific quirks.
+ *
+ * Specifies platform specific configuration of sdhci controller.
+ * Note: A structure for driver specific platform data is used for future
+ * expansion of its usage.
+ */
+struct sdhci_s3c_drv_data {
+	unsigned int	sdhci_quirks;
+};
+
 static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
 {
 	return sdhci_priv(host);
@@ -132,10 +144,10 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
 		return UINT_MAX;
 
 	/*
-	 * Clock divider's step is different as 1 from that of host controller
-	 * when 'clk_type' is S3C_SDHCI_CLK_DIV_EXTERNAL.
+	 * If controller uses a non-standard clock division, find the best clock
+	 * speed possible with selected clock source and skip the division.
 	 */
-	if (ourhost->pdata->clk_type) {
+	if (ourhost->host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
 		rate = clk_round_rate(clksrc, wanted);
 		return wanted - rate;
 	}
@@ -272,6 +284,8 @@ static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host)
 static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
 {
 	struct sdhci_s3c *ourhost = to_s3c(host);
+	unsigned long timeout;
+	u16 clk = 0;
 
 	/* don't bother if the clock is going off */
 	if (clock == 0)
@@ -282,6 +296,25 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
 	clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock);
 
 	host->clock = clock;
+
+	clk = SDHCI_CLOCK_INT_EN;
+	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+	/* Wait max 20 ms */
+	timeout = 20;
+	while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
+		& SDHCI_CLOCK_INT_STABLE)) {
+		if (timeout == 0) {
+			printk(KERN_ERR "%s: Internal clock never "
+				"stabilised.\n", mmc_hostname(host->mmc));
+			return;
+		}
+		timeout--;
+		mdelay(1);
+	}
+
+	clk |= SDHCI_CLOCK_CARD_EN;
+	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
 }
 
 /**
@@ -382,9 +415,17 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc)
 	}
 }
 
+static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data(
+			struct platform_device *pdev)
+{
+	return (struct sdhci_s3c_drv_data *)
+			platform_get_device_id(pdev)->driver_data;
+}
+
 static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
 {
 	struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
+	struct sdhci_s3c_drv_data *drv_data;
 	struct device *dev = &pdev->dev;
 	struct sdhci_host *host;
 	struct sdhci_s3c *sc;
@@ -414,6 +455,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
 		return PTR_ERR(host);
 	}
 
+	drv_data = sdhci_s3c_get_driver_data(pdev);
 	sc = sdhci_priv(host);
 
 	sc->host = host;
@@ -494,6 +536,8 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
 	/* Setup quirks for the controller */
 	host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
 	host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
+	if (drv_data)
+		host->quirks |= drv_data->sdhci_quirks;
 
 #ifndef CONFIG_MMC_SDHCI_S3C_DMA
 
@@ -534,7 +578,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
 	 * If controller does not have internal clock divider,
 	 * we can use overriding functions instead of default.
 	 */
-	if (pdata->clk_type) {
+	if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
 		sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock;
 		sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock;
 		sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock;
@@ -639,9 +683,31 @@ static int sdhci_s3c_resume(struct platform_device *dev)
 #define sdhci_s3c_resume NULL
 #endif
 
+#if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212)
+static struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = {
+	.sdhci_quirks = SDHCI_QUIRK_NONSTANDARD_CLOCK,
+};
+#define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)&exynos4_sdhci_drv_data)
+#else
+#define EXYNOS4_SDHCI_DRV_DATA (kernel_ulong_t)NULL
+#endif
+
+static struct platform_device_id sdhci_s3c_driver_ids[] = {
+	{
+		.name		= "s3c-sdhci",
+		.driver_data	= (kernel_ulong_t)NULL,
+	},
+	{
+		.name		= "exynos4-sdhci",
+		.driver_data	= EXYNOS4_SDHCI_DRV_DATA,
+	},
+};
+MODULE_DEVICE_TABLE(platform, sdhci_s3c_driver_ids);
+
 static struct platform_driver sdhci_s3c_driver = {
 	.probe		= sdhci_s3c_probe,
 	.remove		= __devexit_p(sdhci_s3c_remove),
+	.id_table	= sdhci_s3c_driver_ids,
 	.suspend	= sdhci_s3c_suspend,
 	.resume	        = sdhci_s3c_resume,
 	.driver		= {
-- 
1.6.6.rc2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] arm: exynos4: use 'exynos4-sdhci' as device name for sdhci controllers
  2011-10-04  7:28 [PATCH 0/3] mmc: sdhci-s3c: Remove 'clk_type' member from platform data Thomas Abraham
  2011-10-04  7:28 ` [PATCH 1/3] mmc: sdhci-s3c: Remove usage of clk_type member in " Thomas Abraham
@ 2011-10-04  7:28 ` Thomas Abraham
  2011-10-04  7:28 ` [PATCH 3/3] arm: samsung: remove all uses of clk_type member in sdhci platform data Thomas Abraham
  2 siblings, 0 replies; 6+ messages in thread
From: Thomas Abraham @ 2011-10-04  7:28 UTC (permalink / raw)
  To: linux-arm-kernel

With the addition of platform specific driver data in the sdhci driver
for exynos4, the device name of sdhci controllers on exynos4 is changed
accordingly.

Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/mach-exynos4/clock.c              |   16 ++++++++--------
 arch/arm/mach-exynos4/cpu.c                |    5 +++++
 arch/arm/plat-samsung/include/plat/sdhci.h |   27 +++++++++++++++++++++++++++
 3 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c
index a25c818..d89b45e 100644
--- a/arch/arm/mach-exynos4/clock.c
+++ b/arch/arm/mach-exynos4/clock.c
@@ -495,25 +495,25 @@ static struct clk init_clocks_off[] = {
 		.ctrlbit	= (1 << 0),
 	}, {
 		.name		= "hsmmc",
-		.devname	= "s3c-sdhci.0",
+		.devname	= "exynos4-sdhci.0",
 		.parent		= &clk_aclk_133.clk,
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 5),
 	}, {
 		.name		= "hsmmc",
-		.devname	= "s3c-sdhci.1",
+		.devname	= "exynos4-sdhci.1",
 		.parent		= &clk_aclk_133.clk,
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 6),
 	}, {
 		.name		= "hsmmc",
-		.devname	= "s3c-sdhci.2",
+		.devname	= "exynos4-sdhci.2",
 		.parent		= &clk_aclk_133.clk,
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 7),
 	}, {
 		.name		= "hsmmc",
-		.devname	= "s3c-sdhci.3",
+		.devname	= "exynos4-sdhci.3",
 		.parent		= &clk_aclk_133.clk,
 		.enable		= exynos4_clk_ip_fsys_ctrl,
 		.ctrlbit	= (1 << 8),
@@ -1198,7 +1198,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_mmc",
-			.devname	= "s3c-sdhci.0",
+			.devname	= "exynos4-sdhci.0",
 			.parent		= &clk_dout_mmc0.clk,
 			.enable		= exynos4_clksrc_mask_fsys_ctrl,
 			.ctrlbit	= (1 << 0),
@@ -1207,7 +1207,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_mmc",
-			.devname	= "s3c-sdhci.1",
+			.devname	= "exynos4-sdhci.1",
 			.parent         = &clk_dout_mmc1.clk,
 			.enable		= exynos4_clksrc_mask_fsys_ctrl,
 			.ctrlbit	= (1 << 4),
@@ -1216,7 +1216,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_mmc",
-			.devname	= "s3c-sdhci.2",
+			.devname	= "exynos4-sdhci.2",
 			.parent         = &clk_dout_mmc2.clk,
 			.enable		= exynos4_clksrc_mask_fsys_ctrl,
 			.ctrlbit	= (1 << 8),
@@ -1225,7 +1225,7 @@ static struct clksrc_clk clksrcs[] = {
 	}, {
 		.clk		= {
 			.name		= "sclk_mmc",
-			.devname	= "s3c-sdhci.3",
+			.devname	= "exynos4-sdhci.3",
 			.parent         = &clk_dout_mmc3.clk,
 			.enable		= exynos4_clksrc_mask_fsys_ctrl,
 			.ctrlbit	= (1 << 12),
diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c
index 2aa3df0..8f0f897 100644
--- a/arch/arm/mach-exynos4/cpu.c
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -175,6 +175,11 @@ void __init exynos4_map_io(void)
 	s3c_fimc_setname(2, "exynos4-fimc");
 	s3c_fimc_setname(3, "exynos4-fimc");
 
+	s3c_sdhci_setname(0, "exynos4-sdhci");
+	s3c_sdhci_setname(1, "exynos4-sdhci");
+	s3c_sdhci_setname(2, "exynos4-sdhci");
+	s3c_sdhci_setname(3, "exynos4-sdhci");
+
 	/* The I2C bus controllers are directly compatible with s3c2440 */
 	s3c_i2c0_setname("s3c2440-i2c");
 	s3c_i2c1_setname("s3c2440-i2c");
diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h
index e7b3c75..8f9a7d7 100644
--- a/arch/arm/plat-samsung/include/plat/sdhci.h
+++ b/arch/arm/plat-samsung/include/plat/sdhci.h
@@ -18,6 +18,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;
@@ -340,4 +342,29 @@ static inline void exynos4_default_sdhci3(void) { }
 
 #endif /* CONFIG_EXYNOS4_SETUP_SDHCI */
 
+static inline void s3c_sdhci_setname(int id, char *name)
+{
+	switch (id) {
+#ifdef CONFIG_S3C_DEV_HSMMC
+	case 0:
+		s3c_device_hsmmc0.name = name;
+		break;
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC1
+	case 1:
+		s3c_device_hsmmc1.name = name;
+		break;
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC2
+	case 2:
+		s3c_device_hsmmc2.name = name;
+		break;
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC3
+	case 3:
+		s3c_device_hsmmc3.name = name;
+		break;
+#endif
+	}
+}
 #endif /* __PLAT_S3C_SDHCI_H */
-- 
1.6.6.rc2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/3] arm: samsung: remove all uses of clk_type member in sdhci platform data
  2011-10-04  7:28 [PATCH 0/3] mmc: sdhci-s3c: Remove 'clk_type' member from platform data Thomas Abraham
  2011-10-04  7:28 ` [PATCH 1/3] mmc: sdhci-s3c: Remove usage of clk_type member in " Thomas Abraham
  2011-10-04  7:28 ` [PATCH 2/3] arm: exynos4: use 'exynos4-sdhci' as device name for sdhci controllers Thomas Abraham
@ 2011-10-04  7:28 ` Thomas Abraham
  2 siblings, 0 replies; 6+ messages in thread
From: Thomas Abraham @ 2011-10-04  7:28 UTC (permalink / raw)
  To: linux-arm-kernel

The sdhci driver is modified to be independent of clk_type member in the sdhci
platform data. Hence, all usage of clk_type in platform code is removed.

Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: JeongHyeon Kim <jhkim@insignal.co.kr>
Cc: Kukjin Kim <kgene.kim@samsung.com>
Cc: Changhwan Youn <chaos.youn@samsung.com>
Cc: Alim Akhtar <alim.akhtar@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
 arch/arm/mach-exynos4/mach-armlex4210.c     |    3 ---
 arch/arm/mach-exynos4/mach-nuri.c           |    3 ---
 arch/arm/mach-exynos4/mach-origen.c         |    2 --
 arch/arm/mach-exynos4/mach-smdk4212.c       |    2 --
 arch/arm/mach-exynos4/mach-smdkv310.c       |    4 ----
 arch/arm/mach-exynos4/mach-universal_c210.c |    2 --
 arch/arm/plat-samsung/dev-hsmmc.c           |    1 -
 arch/arm/plat-samsung/dev-hsmmc1.c          |    1 -
 arch/arm/plat-samsung/dev-hsmmc2.c          |    1 -
 arch/arm/plat-samsung/dev-hsmmc3.c          |    1 -
 arch/arm/plat-samsung/include/plat/sdhci.h  |    7 -------
 arch/arm/plat-samsung/platformdata.c        |    2 --
 12 files changed, 0 insertions(+), 29 deletions(-)

diff --git a/arch/arm/mach-exynos4/mach-armlex4210.c b/arch/arm/mach-exynos4/mach-armlex4210.c
index b482c62..8bb2c48 100644
--- a/arch/arm/mach-exynos4/mach-armlex4210.c
+++ b/arch/arm/mach-exynos4/mach-armlex4210.c
@@ -75,7 +75,6 @@ static struct s3c2410_uartcfg armlex4210_uartcfgs[] __initdata = {
 
 static struct s3c_sdhci_platdata armlex4210_hsmmc0_pdata __initdata = {
 	.cd_type		= S3C_SDHCI_CD_PERMANENT,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 #ifdef CONFIG_EXYNOS4_SDHCI_CH0_8BIT
 	.max_width		= 8,
 	.host_caps		= MMC_CAP_8_BIT_DATA,
@@ -86,13 +85,11 @@ static struct s3c_sdhci_platdata armlex4210_hsmmc2_pdata __initdata = {
 	.cd_type		= S3C_SDHCI_CD_GPIO,
 	.ext_cd_gpio		= EXYNOS4_GPX2(5),
 	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 	.max_width		= 4,
 };
 
 static struct s3c_sdhci_platdata armlex4210_hsmmc3_pdata __initdata = {
 	.cd_type		= S3C_SDHCI_CD_PERMANENT,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 	.max_width		= 4,
 };
 
diff --git a/arch/arm/mach-exynos4/mach-nuri.c b/arch/arm/mach-exynos4/mach-nuri.c
index bbd13f4..00b4b6f 100644
--- a/arch/arm/mach-exynos4/mach-nuri.c
+++ b/arch/arm/mach-exynos4/mach-nuri.c
@@ -101,7 +101,6 @@ static struct s3c_sdhci_platdata nuri_hsmmc0_data __initdata = {
 				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
 				MMC_CAP_DISABLE | MMC_CAP_ERASE),
 	.cd_type		= S3C_SDHCI_CD_PERMANENT,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
 
 static struct regulator_consumer_supply emmc_supplies[] = {
@@ -143,7 +142,6 @@ static struct s3c_sdhci_platdata nuri_hsmmc2_data __initdata = {
 	.ext_cd_gpio		= EXYNOS4_GPX3(3),	/* XEINT_27 */
 	.ext_cd_gpio_invert	= 1,
 	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
 
 /* WLAN */
@@ -152,7 +150,6 @@ static struct s3c_sdhci_platdata nuri_hsmmc3_data __initdata = {
 	.host_caps		= MMC_CAP_4_BIT_DATA |
 				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
 	.cd_type		= S3C_SDHCI_CD_EXTERNAL,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
 
 static void __init nuri_sdhci_init(void)
diff --git a/arch/arm/mach-exynos4/mach-origen.c b/arch/arm/mach-exynos4/mach-origen.c
index 421294b..82dfdc3 100644
--- a/arch/arm/mach-exynos4/mach-origen.c
+++ b/arch/arm/mach-exynos4/mach-origen.c
@@ -80,12 +80,10 @@ static struct s3c2410_uartcfg origen_uartcfgs[] __initdata = {
 
 static struct s3c_sdhci_platdata origen_hsmmc0_pdata __initdata = {
 	.cd_type		= S3C_SDHCI_CD_INTERNAL,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
 
 static struct s3c_sdhci_platdata origen_hsmmc2_pdata __initdata = {
 	.cd_type		= S3C_SDHCI_CD_INTERNAL,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
 
 /* USB EHCI */
diff --git a/arch/arm/mach-exynos4/mach-smdk4212.c b/arch/arm/mach-exynos4/mach-smdk4212.c
index 8c41ae1..b460652 100644
--- a/arch/arm/mach-exynos4/mach-smdk4212.c
+++ b/arch/arm/mach-exynos4/mach-smdk4212.c
@@ -83,7 +83,6 @@ static struct s3c2410_uartcfg smdk4212_uartcfgs[] __initdata = {
 
 static struct s3c_sdhci_platdata smdk4212_hsmmc2_pdata __initdata = {
 	.cd_type		= S3C_SDHCI_CD_INTERNAL,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 #ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT
 	.max_width		= 8,
 	.host_caps		= MMC_CAP_8_BIT_DATA,
@@ -92,7 +91,6 @@ static struct s3c_sdhci_platdata smdk4212_hsmmc2_pdata __initdata = {
 
 static struct s3c_sdhci_platdata smdk4212_hsmmc3_pdata __initdata = {
 	.cd_type		= S3C_SDHCI_CD_INTERNAL,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
 
 static struct regulator_consumer_supply max8997_buck1 =
diff --git a/arch/arm/mach-exynos4/mach-smdkv310.c b/arch/arm/mach-exynos4/mach-smdkv310.c
index c74b2db..31a64d8 100644
--- a/arch/arm/mach-exynos4/mach-smdkv310.c
+++ b/arch/arm/mach-exynos4/mach-smdkv310.c
@@ -90,7 +90,6 @@ static struct s3c2410_uartcfg smdkv310_uartcfgs[] __initdata = {
 
 static struct s3c_sdhci_platdata smdkv310_hsmmc0_pdata __initdata = {
 	.cd_type		= S3C_SDHCI_CD_INTERNAL,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 #ifdef CONFIG_EXYNOS4_SDHCI_CH0_8BIT
 	.max_width		= 8,
 	.host_caps		= MMC_CAP_8_BIT_DATA,
@@ -101,12 +100,10 @@ static struct s3c_sdhci_platdata smdkv310_hsmmc1_pdata __initdata = {
 	.cd_type		= S3C_SDHCI_CD_GPIO,
 	.ext_cd_gpio		= EXYNOS4_GPK0(2),
 	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
 
 static struct s3c_sdhci_platdata smdkv310_hsmmc2_pdata __initdata = {
 	.cd_type		= S3C_SDHCI_CD_INTERNAL,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 #ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT
 	.max_width		= 8,
 	.host_caps		= MMC_CAP_8_BIT_DATA,
@@ -117,7 +114,6 @@ static struct s3c_sdhci_platdata smdkv310_hsmmc3_pdata __initdata = {
 	.cd_type		= S3C_SDHCI_CD_GPIO,
 	.ext_cd_gpio		= EXYNOS4_GPK2(2),
 	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
 
 static void lcd_lte480wv_set_power(struct plat_lcd_data *pd,
diff --git a/arch/arm/mach-exynos4/mach-universal_c210.c b/arch/arm/mach-exynos4/mach-universal_c210.c
index 18cf5c7..0556feb 100644
--- a/arch/arm/mach-exynos4/mach-universal_c210.c
+++ b/arch/arm/mach-exynos4/mach-universal_c210.c
@@ -737,7 +737,6 @@ static struct s3c_sdhci_platdata universal_hsmmc0_data __initdata = {
 				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
 				MMC_CAP_DISABLE),
 	.cd_type		= S3C_SDHCI_CD_PERMANENT,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
 
 static struct regulator_consumer_supply mmc0_supplies[] = {
@@ -778,7 +777,6 @@ static struct s3c_sdhci_platdata universal_hsmmc2_data __initdata = {
 	.ext_cd_gpio		= EXYNOS4_GPX3(4),      /* XEINT_28 */
 	.ext_cd_gpio_invert	= 1,
 	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
 };
 
 /* WiFi */
diff --git a/arch/arm/plat-samsung/dev-hsmmc.c b/arch/arm/plat-samsung/dev-hsmmc.c
index 06825c4..ea0291f 100644
--- a/arch/arm/plat-samsung/dev-hsmmc.c
+++ b/arch/arm/plat-samsung/dev-hsmmc.c
@@ -41,7 +41,6 @@ struct s3c_sdhci_platdata s3c_hsmmc0_def_platdata = {
 	.max_width	= 4,
 	.host_caps	= (MMC_CAP_4_BIT_DATA |
 			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
-	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
 };
 
 struct platform_device s3c_device_hsmmc0 = {
diff --git a/arch/arm/plat-samsung/dev-hsmmc1.c b/arch/arm/plat-samsung/dev-hsmmc1.c
index 4524ef4..56dbe7a 100644
--- a/arch/arm/plat-samsung/dev-hsmmc1.c
+++ b/arch/arm/plat-samsung/dev-hsmmc1.c
@@ -41,7 +41,6 @@ struct s3c_sdhci_platdata s3c_hsmmc1_def_platdata = {
 	.max_width	= 4,
 	.host_caps	= (MMC_CAP_4_BIT_DATA |
 			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
-	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
 };
 
 struct platform_device s3c_device_hsmmc1 = {
diff --git a/arch/arm/plat-samsung/dev-hsmmc2.c b/arch/arm/plat-samsung/dev-hsmmc2.c
index 9cede96..916e11b 100644
--- a/arch/arm/plat-samsung/dev-hsmmc2.c
+++ b/arch/arm/plat-samsung/dev-hsmmc2.c
@@ -42,7 +42,6 @@ struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata = {
 	.max_width	= 4,
 	.host_caps	= (MMC_CAP_4_BIT_DATA |
 			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
-	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
 };
 
 struct platform_device s3c_device_hsmmc2 = {
diff --git a/arch/arm/plat-samsung/dev-hsmmc3.c b/arch/arm/plat-samsung/dev-hsmmc3.c
index 0358ef4..8f06670 100644
--- a/arch/arm/plat-samsung/dev-hsmmc3.c
+++ b/arch/arm/plat-samsung/dev-hsmmc3.c
@@ -45,7 +45,6 @@ struct s3c_sdhci_platdata s3c_hsmmc3_def_platdata = {
 	.max_width	= 4,
 	.host_caps	= (MMC_CAP_4_BIT_DATA |
 			   MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
-	.clk_type	= S3C_SDHCI_CLK_DIV_INTERNAL,
 };
 
 struct platform_device s3c_device_hsmmc3 = {
diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h
index 8f9a7d7..39a70ec 100644
--- a/arch/arm/plat-samsung/include/plat/sdhci.h
+++ b/arch/arm/plat-samsung/include/plat/sdhci.h
@@ -33,17 +33,11 @@ enum cd_types {
 	S3C_SDHCI_CD_PERMANENT,	/* no CD line, card permanently wired to host */
 };
 
-enum clk_types {
-	S3C_SDHCI_CLK_DIV_INTERNAL,	/* use mmc internal clock divider */
-	S3C_SDHCI_CLK_DIV_EXTERNAL,	/* use external clock divider */
-};
-
 /**
  * struct s3c_sdhci_platdata() - Platform device data for Samsung SDHCI
  * @max_width: The maximum number of data bits supported.
  * @host_caps: Standard MMC host capabilities bit field.
  * @cd_type: Type of Card Detection method (see cd_types enum above)
- * @clk_type: Type of clock divider method (see clk_types enum above)
  * @ext_cd_init: Initialize external card detect subsystem. Called on
  *		 sdhci-s3c driver probe when cd_type == S3C_SDHCI_CD_EXTERNAL.
  *		 notify_func argument is a callback to the sdhci-s3c driver
@@ -66,7 +60,6 @@ struct s3c_sdhci_platdata {
 	unsigned int	max_width;
 	unsigned int	host_caps;
 	enum cd_types	cd_type;
-	enum clk_types	clk_type;
 
 	char		**clocks;	/* set of clock sources */
 
diff --git a/arch/arm/plat-samsung/platformdata.c b/arch/arm/plat-samsung/platformdata.c
index 4c9a207..88c5e7c 100644
--- a/arch/arm/plat-samsung/platformdata.c
+++ b/arch/arm/plat-samsung/platformdata.c
@@ -52,6 +52,4 @@ void s3c_sdhci_set_platdata(struct s3c_sdhci_platdata *pd,
 		set->cfg_gpio = pd->cfg_gpio;
 	if (pd->host_caps)
 		set->host_caps |= pd->host_caps;
-	if (pd->clk_type)
-		set->clk_type = pd->clk_type;
 }
-- 
1.6.6.rc2

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 1/3] mmc: sdhci-s3c: Remove usage of clk_type member in platform data
  2011-10-04  7:28 ` [PATCH 1/3] mmc: sdhci-s3c: Remove usage of clk_type member in " Thomas Abraham
@ 2011-10-04  7:53   ` Kyungmin Park
  2011-10-04  8:15     ` Thomas Abraham
  0 siblings, 1 reply; 6+ messages in thread
From: Kyungmin Park @ 2011-10-04  7:53 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Tue, Oct 4, 2011 at 4:28 PM, Thomas Abraham
<thomas.abraham@linaro.org> wrote:
> SDHCI controllers on Exynos4 do not include the sdclk divider as per the
> sdhci controller specification. This case can be represented using the
> sdhci quirk SDHCI_QUIRK_NONSTANDARD_CLOCK instead of using an additional
> enum type definition 'clk_types'.
>
> Hence, usage of clk_type member in platform data is removed and the sdhci
> quirk is used. In addition to that, since this qurik is SoC specific,
> driver data is introduced to represent controllers on SoC's that require
> this quirk.
Right.
>
> Cc: Ben Dooks <ben-linux@fluff.org>
> Cc: Jeongbae Seo <jeongbae.seo@samsung.com>
> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
> ---
> In the function 'sdhci_cmu_set_clock', the code that waits for a stable
> sdclk clock is replicated from 'sdhci_set_clock' function. This portion
> of code is replicated in sdhci-cns3xxx driver as well. This duplication
> could have been avoid by adding a new function in sdhci host controller
> driver that waits for stable sdclk and sdhci-s3c/sdhci-cns3xxx can be
> the users of the new function. If adding a new function in sdhci host
> controller driver is acceptable, an additional patch in this series
> can be added that creates the new function that waits for stable sdclk.
>
> ?drivers/mmc/host/sdhci-s3c.c | ? 74 +++++++++++++++++++++++++++++++++++++++--
> ?1 files changed, 70 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
> index 82709b6..b29e734 100644
> --- a/drivers/mmc/host/sdhci-s3c.c
> +++ b/drivers/mmc/host/sdhci-s3c.c
> @@ -53,6 +53,18 @@ struct sdhci_s3c {
> ? ? ? ?struct clk ? ? ? ? ? ? ?*clk_bus[MAX_BUS_CLK];
> ?};
>
> +/**
> + * struct sdhci_s3c_driver_data - S3C SDHCI platform specific driver data
> + * @sdhci_quirks: sdhci host specific quirks.
> + *
> + * Specifies platform specific configuration of sdhci controller.
> + * Note: A structure for driver specific platform data is used for future
> + * expansion of its usage.
> + */
> +struct sdhci_s3c_drv_data {
> + ? ? ? unsigned int ? ?sdhci_quirks;
> +};
> +
> ?static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
> ?{
> ? ? ? ?return sdhci_priv(host);
> @@ -132,10 +144,10 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
> ? ? ? ? ? ? ? ?return UINT_MAX;
>
> ? ? ? ?/*
> - ? ? ? ?* Clock divider's step is different as 1 from that of host controller
> - ? ? ? ?* when 'clk_type' is S3C_SDHCI_CLK_DIV_EXTERNAL.
> + ? ? ? ?* If controller uses a non-standard clock division, find the best clock
> + ? ? ? ?* speed possible with selected clock source and skip the division.
> ? ? ? ? */
> - ? ? ? if (ourhost->pdata->clk_type) {
> + ? ? ? if (ourhost->host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
> ? ? ? ? ? ? ? ?rate = clk_round_rate(clksrc, wanted);
> ? ? ? ? ? ? ? ?return wanted - rate;
> ? ? ? ?}
> @@ -272,6 +284,8 @@ static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host)
> ?static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
> ?{
> ? ? ? ?struct sdhci_s3c *ourhost = to_s3c(host);
> + ? ? ? unsigned long timeout;
> + ? ? ? u16 clk = 0;
>
> ? ? ? ?/* don't bother if the clock is going off */
> ? ? ? ?if (clock == 0)
> @@ -282,6 +296,25 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
> ? ? ? ?clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock);
>
> ? ? ? ?host->clock = clock;
> +
> + ? ? ? clk = SDHCI_CLOCK_INT_EN;
> + ? ? ? sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
> +
> + ? ? ? /* Wait max 20 ms */
> + ? ? ? timeout = 20;
> + ? ? ? while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
> + ? ? ? ? ? ? ? & SDHCI_CLOCK_INT_STABLE)) {
> + ? ? ? ? ? ? ? if (timeout == 0) {
> + ? ? ? ? ? ? ? ? ? ? ? printk(KERN_ERR "%s: Internal clock never "
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "stabilised.\n", mmc_hostname(host->mmc));
> + ? ? ? ? ? ? ? ? ? ? ? return;
> + ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? timeout--;
> + ? ? ? ? ? ? ? mdelay(1);
> + ? ? ? }
> +
> + ? ? ? clk |= SDHCI_CLOCK_CARD_EN;
> + ? ? ? sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
> ?}
>
> ?/**
> @@ -382,9 +415,17 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc)
> ? ? ? ?}
> ?}
>
> +static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data(
> + ? ? ? ? ? ? ? ? ? ? ? struct platform_device *pdev)
> +{
> + ? ? ? return (struct sdhci_s3c_drv_data *)
> + ? ? ? ? ? ? ? ? ? ? ? platform_get_device_id(pdev)->driver_data;
> +}
> +
> ?static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
> ?{
> ? ? ? ?struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
> + ? ? ? struct sdhci_s3c_drv_data *drv_data;
> ? ? ? ?struct device *dev = &pdev->dev;
> ? ? ? ?struct sdhci_host *host;
> ? ? ? ?struct sdhci_s3c *sc;
> @@ -414,6 +455,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
> ? ? ? ? ? ? ? ?return PTR_ERR(host);
> ? ? ? ?}
>
> + ? ? ? drv_data = sdhci_s3c_get_driver_data(pdev);
> ? ? ? ?sc = sdhci_priv(host);
>
> ? ? ? ?sc->host = host;
> @@ -494,6 +536,8 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
> ? ? ? ?/* Setup quirks for the controller */
> ? ? ? ?host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
> ? ? ? ?host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
> + ? ? ? if (drv_data)
> + ? ? ? ? ? ? ? host->quirks |= drv_data->sdhci_quirks;
>
> ?#ifndef CONFIG_MMC_SDHCI_S3C_DMA
>
> @@ -534,7 +578,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
> ? ? ? ? * If controller does not have internal clock divider,
> ? ? ? ? * we can use overriding functions instead of default.
> ? ? ? ? */
> - ? ? ? if (pdata->clk_type) {
> + ? ? ? if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
> ? ? ? ? ? ? ? ?sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock;
> ? ? ? ? ? ? ? ?sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock;
> ? ? ? ? ? ? ? ?sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock;
> @@ -639,9 +683,31 @@ static int sdhci_s3c_resume(struct platform_device *dev)
> ?#define sdhci_s3c_resume NULL
> ?#endif
>
> +#if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212)
> +static struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = {
> + ? ? ? .sdhci_quirks = SDHCI_QUIRK_NONSTANDARD_CLOCK,
> +};
> +#define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)&exynos4_sdhci_drv_data)
> +#else
> +#define EXYNOS4_SDHCI_DRV_DATA (kernel_ulong_t)NULL
> +#endif
It's too small to save the memory. I think no need to guard the exynos
driver data with ifdef/endif.
> +
> +static struct platform_device_id sdhci_s3c_driver_ids[] = {
> + ? ? ? {
> + ? ? ? ? ? ? ? .name ? ? ? ? ? = "s3c-sdhci",
> + ? ? ? ? ? ? ? .driver_data ? ?= (kernel_ulong_t)NULL,
> + ? ? ? },
> + ? ? ? {
> + ? ? ? ? ? ? ? .name ? ? ? ? ? = "exynos4-sdhci",
> + ? ? ? ? ? ? ? .driver_data ? ?= EXYNOS4_SDHCI_DRV_DATA,
> + ? ? ? },
> +};
> +MODULE_DEVICE_TABLE(platform, sdhci_s3c_driver_ids);

Do you have a plan to use the sdhci-pltfm.c as other drivers did?
some drivers are already use it and support OF features.

Thank you,
Kyungmin Park
> +
> ?static struct platform_driver sdhci_s3c_driver = {
> ? ? ? ?.probe ? ? ? ? ?= sdhci_s3c_probe,
> ? ? ? ?.remove ? ? ? ? = __devexit_p(sdhci_s3c_remove),
> + ? ? ? .id_table ? ? ? = sdhci_s3c_driver_ids,
> ? ? ? ?.suspend ? ? ? ?= sdhci_s3c_suspend,
> ? ? ? ?.resume ? ? ? ? = sdhci_s3c_resume,
> ? ? ? ?.driver ? ? ? ? = {
> --
> 1.6.6.rc2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/3] mmc: sdhci-s3c: Remove usage of clk_type member in platform data
  2011-10-04  7:53   ` Kyungmin Park
@ 2011-10-04  8:15     ` Thomas Abraham
  0 siblings, 0 replies; 6+ messages in thread
From: Thomas Abraham @ 2011-10-04  8:15 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mr. Park,

On 4 October 2011 13:23, Kyungmin Park <kmpark@infradead.org> wrote:
> Hi,
>
> On Tue, Oct 4, 2011 at 4:28 PM, Thomas Abraham
> <thomas.abraham@linaro.org> wrote:
>> SDHCI controllers on Exynos4 do not include the sdclk divider as per the
>> sdhci controller specification. This case can be represented using the
>> sdhci quirk SDHCI_QUIRK_NONSTANDARD_CLOCK instead of using an additional
>> enum type definition 'clk_types'.
>>
>> Hence, usage of clk_type member in platform data is removed and the sdhci
>> quirk is used. In addition to that, since this qurik is SoC specific,
>> driver data is introduced to represent controllers on SoC's that require
>> this quirk.
> Right.
>>
>> Cc: Ben Dooks <ben-linux@fluff.org>
>> Cc: Jeongbae Seo <jeongbae.seo@samsung.com>
>> Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
>> ---
>> In the function 'sdhci_cmu_set_clock', the code that waits for a stable
>> sdclk clock is replicated from 'sdhci_set_clock' function. This portion
>> of code is replicated in sdhci-cns3xxx driver as well. This duplication
>> could have been avoid by adding a new function in sdhci host controller
>> driver that waits for stable sdclk and sdhci-s3c/sdhci-cns3xxx can be
>> the users of the new function. If adding a new function in sdhci host
>> controller driver is acceptable, an additional patch in this series
>> can be added that creates the new function that waits for stable sdclk.
>>
>> ?drivers/mmc/host/sdhci-s3c.c | ? 74 +++++++++++++++++++++++++++++++++++++++--
>> ?1 files changed, 70 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
>> index 82709b6..b29e734 100644
>> --- a/drivers/mmc/host/sdhci-s3c.c
>> +++ b/drivers/mmc/host/sdhci-s3c.c
>> @@ -53,6 +53,18 @@ struct sdhci_s3c {
>> ? ? ? ?struct clk ? ? ? ? ? ? ?*clk_bus[MAX_BUS_CLK];
>> ?};
>>
>> +/**
>> + * struct sdhci_s3c_driver_data - S3C SDHCI platform specific driver data
>> + * @sdhci_quirks: sdhci host specific quirks.
>> + *
>> + * Specifies platform specific configuration of sdhci controller.
>> + * Note: A structure for driver specific platform data is used for future
>> + * expansion of its usage.
>> + */
>> +struct sdhci_s3c_drv_data {
>> + ? ? ? unsigned int ? ?sdhci_quirks;
>> +};
>> +
>> ?static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
>> ?{
>> ? ? ? ?return sdhci_priv(host);
>> @@ -132,10 +144,10 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
>> ? ? ? ? ? ? ? ?return UINT_MAX;
>>
>> ? ? ? ?/*
>> - ? ? ? ?* Clock divider's step is different as 1 from that of host controller
>> - ? ? ? ?* when 'clk_type' is S3C_SDHCI_CLK_DIV_EXTERNAL.
>> + ? ? ? ?* If controller uses a non-standard clock division, find the best clock
>> + ? ? ? ?* speed possible with selected clock source and skip the division.
>> ? ? ? ? */
>> - ? ? ? if (ourhost->pdata->clk_type) {
>> + ? ? ? if (ourhost->host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
>> ? ? ? ? ? ? ? ?rate = clk_round_rate(clksrc, wanted);
>> ? ? ? ? ? ? ? ?return wanted - rate;
>> ? ? ? ?}
>> @@ -272,6 +284,8 @@ static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host)
>> ?static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
>> ?{
>> ? ? ? ?struct sdhci_s3c *ourhost = to_s3c(host);
>> + ? ? ? unsigned long timeout;
>> + ? ? ? u16 clk = 0;
>>
>> ? ? ? ?/* don't bother if the clock is going off */
>> ? ? ? ?if (clock == 0)
>> @@ -282,6 +296,25 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
>> ? ? ? ?clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock);
>>
>> ? ? ? ?host->clock = clock;
>> +
>> + ? ? ? clk = SDHCI_CLOCK_INT_EN;
>> + ? ? ? sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
>> +
>> + ? ? ? /* Wait max 20 ms */
>> + ? ? ? timeout = 20;
>> + ? ? ? while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
>> + ? ? ? ? ? ? ? & SDHCI_CLOCK_INT_STABLE)) {
>> + ? ? ? ? ? ? ? if (timeout == 0) {
>> + ? ? ? ? ? ? ? ? ? ? ? printk(KERN_ERR "%s: Internal clock never "
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "stabilised.\n", mmc_hostname(host->mmc));
>> + ? ? ? ? ? ? ? ? ? ? ? return;
>> + ? ? ? ? ? ? ? }
>> + ? ? ? ? ? ? ? timeout--;
>> + ? ? ? ? ? ? ? mdelay(1);
>> + ? ? ? }
>> +
>> + ? ? ? clk |= SDHCI_CLOCK_CARD_EN;
>> + ? ? ? sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
>> ?}
>>
>> ?/**
>> @@ -382,9 +415,17 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc)
>> ? ? ? ?}
>> ?}
>>
>> +static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data(
>> + ? ? ? ? ? ? ? ? ? ? ? struct platform_device *pdev)
>> +{
>> + ? ? ? return (struct sdhci_s3c_drv_data *)
>> + ? ? ? ? ? ? ? ? ? ? ? platform_get_device_id(pdev)->driver_data;
>> +}
>> +
>> ?static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
>> ?{
>> ? ? ? ?struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
>> + ? ? ? struct sdhci_s3c_drv_data *drv_data;
>> ? ? ? ?struct device *dev = &pdev->dev;
>> ? ? ? ?struct sdhci_host *host;
>> ? ? ? ?struct sdhci_s3c *sc;
>> @@ -414,6 +455,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
>> ? ? ? ? ? ? ? ?return PTR_ERR(host);
>> ? ? ? ?}
>>
>> + ? ? ? drv_data = sdhci_s3c_get_driver_data(pdev);
>> ? ? ? ?sc = sdhci_priv(host);
>>
>> ? ? ? ?sc->host = host;
>> @@ -494,6 +536,8 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
>> ? ? ? ?/* Setup quirks for the controller */
>> ? ? ? ?host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
>> ? ? ? ?host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
>> + ? ? ? if (drv_data)
>> + ? ? ? ? ? ? ? host->quirks |= drv_data->sdhci_quirks;
>>
>> ?#ifndef CONFIG_MMC_SDHCI_S3C_DMA
>>
>> @@ -534,7 +578,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
>> ? ? ? ? * If controller does not have internal clock divider,
>> ? ? ? ? * we can use overriding functions instead of default.
>> ? ? ? ? */
>> - ? ? ? if (pdata->clk_type) {
>> + ? ? ? if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
>> ? ? ? ? ? ? ? ?sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock;
>> ? ? ? ? ? ? ? ?sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock;
>> ? ? ? ? ? ? ? ?sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock;
>> @@ -639,9 +683,31 @@ static int sdhci_s3c_resume(struct platform_device *dev)
>> ?#define sdhci_s3c_resume NULL
>> ?#endif
>>
>> +#if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212)
>> +static struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = {
>> + ? ? ? .sdhci_quirks = SDHCI_QUIRK_NONSTANDARD_CLOCK,
>> +};
>> +#define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)&exynos4_sdhci_drv_data)
>> +#else
>> +#define EXYNOS4_SDHCI_DRV_DATA (kernel_ulong_t)NULL
>> +#endif
> It's too small to save the memory. I think no need to guard the exynos
> driver data with ifdef/endif.


There could be other elements added to the 'sdhci_s3c_drv_data'
structure as new variants of sdhci-s3c controller would appear in
future SoC. I am not aware of any such variations in the upcoming
SoC's but this was done taking into consideration that there could be
slight variations which the driver would have to support.


>> +
>> +static struct platform_device_id sdhci_s3c_driver_ids[] = {
>> + ? ? ? {
>> + ? ? ? ? ? ? ? .name ? ? ? ? ? = "s3c-sdhci",
>> + ? ? ? ? ? ? ? .driver_data ? ?= (kernel_ulong_t)NULL,
>> + ? ? ? },
>> + ? ? ? {
>> + ? ? ? ? ? ? ? .name ? ? ? ? ? = "exynos4-sdhci",
>> + ? ? ? ? ? ? ? .driver_data ? ?= EXYNOS4_SDHCI_DRV_DATA,
>> + ? ? ? },
>> +};
>> +MODULE_DEVICE_TABLE(platform, sdhci_s3c_driver_ids);
>
> Do you have a plan to use the sdhci-pltfm.c as other drivers did?
> some drivers are already use it and support OF features.

I did check few months back if sdhci-pltfm.c can be used for sdhci-s3c
drivers but due to slightly complex operations which sdhci-s3c
handles, I did not try to base samsung sdhci driver support on
sdhci-pltfm.c. So, at present, I do not have a plan to move to
sdhci-pltfm.c.

>
> Thank you,
> Kyungmin Park


Thanks for your review and comments.

Regards,
Thomas.

>> +
>> ?static struct platform_driver sdhci_s3c_driver = {
>> ? ? ? ?.probe ? ? ? ? ?= sdhci_s3c_probe,
>> ? ? ? ?.remove ? ? ? ? = __devexit_p(sdhci_s3c_remove),
>> + ? ? ? .id_table ? ? ? = sdhci_s3c_driver_ids,
>> ? ? ? ?.suspend ? ? ? ?= sdhci_s3c_suspend,
>> ? ? ? ?.resume ? ? ? ? = sdhci_s3c_resume,
>> ? ? ? ?.driver ? ? ? ? = {
>> --
>> 1.6.6.rc2
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>>
>

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2011-10-04  8:15 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-10-04  7:28 [PATCH 0/3] mmc: sdhci-s3c: Remove 'clk_type' member from platform data Thomas Abraham
2011-10-04  7:28 ` [PATCH 1/3] mmc: sdhci-s3c: Remove usage of clk_type member in " Thomas Abraham
2011-10-04  7:53   ` Kyungmin Park
2011-10-04  8:15     ` Thomas Abraham
2011-10-04  7:28 ` [PATCH 2/3] arm: exynos4: use 'exynos4-sdhci' as device name for sdhci controllers Thomas Abraham
2011-10-04  7:28 ` [PATCH 3/3] arm: samsung: remove all uses of clk_type member in sdhci platform data Thomas Abraham

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).