From: thomas.abraham@linaro.org (Thomas Abraham)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v3 1/6] mmc: sdhci-s3c: Remove usage of clk_type member in platform data
Date: Tue, 31 Jan 2012 23:26:11 +0530 [thread overview]
Message-ID: <1328032576-9269-2-git-send-email-thomas.abraham@linaro.org> (raw)
In-Reply-To: <1328032576-9269-1-git-send-email-thomas.abraham@linaro.org>
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>
---
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 1af756e..e1b685d 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;
@@ -491,6 +533,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;
@@ -647,9 +691,31 @@ static const struct dev_pm_ops sdhci_s3c_pmops = {
#define SDHCI_S3C_PMOPS 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,
.driver = {
.owner = THIS_MODULE,
.name = "s3c-sdhci",
--
1.6.6.rc2
next prev parent reply other threads:[~2012-01-31 17:56 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-01-31 17:56 [PATCH v3 0/6] mmc: sdhci-s3c: Rework platform data and add device tree support Thomas Abraham
2012-01-31 17:56 ` Thomas Abraham [this message]
2012-01-31 17:56 ` [PATCH v3 2/6] arm: exynos4: use 'exynos4-sdhci' as device name for sdhci controllers Thomas Abraham
2012-01-31 17:56 ` [PATCH v3 3/6] arm: samsung: remove all uses of clk_type member in sdhci platform data Thomas Abraham
2012-01-31 17:56 ` [PATCH v3 4/6] mmc: sdhci-s3c: derive transfer width host capability from max_width in " Thomas Abraham
2012-01-31 19:12 ` Sergei Shtylyov
2012-01-31 17:56 ` [PATCH v3 5/6] mmc: sdhci-s3c: Keep a copy of platform data and use it Thomas Abraham
2012-01-31 17:56 ` [PATCH v3 6/6] mmc: sdhci-s3c: Add device tree support Thomas Abraham
2012-01-31 20:08 ` Grant Likely
2012-02-01 18:21 ` Karol Lewandowski
2012-03-27 16:15 ` Arnd Bergmann
2012-03-27 16:19 ` Arnd Bergmann
2012-03-30 6:33 ` Viresh Kumar
2012-03-30 11:36 ` Arnd Bergmann
2012-03-30 15:48 ` Stephen Warren
2012-03-30 18:45 ` Arnd Bergmann
2012-04-01 11:29 ` Mark Brown
2012-05-13 4:14 ` [PATCH v2] mmc: dt: Consolidate DT bindings Chris Ball
2012-05-13 19:29 ` Guennadi Liakhovetski
2012-05-13 19:46 ` Arnd Bergmann
2012-05-13 20:10 ` Chris Ball
2012-05-14 19:53 ` Arnd Bergmann
2012-04-09 14:48 ` [PATCH v3 6/6] mmc: sdhci-s3c: Add device tree support Chris Ball
2012-04-10 21:37 ` Chris Ball
2012-02-09 13:42 ` [PATCH v3 0/6] mmc: sdhci-s3c: Rework platform data and add " Kukjin Kim
2012-02-11 21:37 ` Chris Ball
2012-02-16 13:04 ` Kukjin Kim
2012-02-16 13:08 ` Chris Ball
2012-02-21 11:37 ` Kukjin Kim
2012-02-21 13:17 ` Chris Ball
2012-02-22 12:58 ` Mark Brown
2012-03-02 20:40 ` Chris Ball
2012-03-03 0:44 ` Kukjin Kim
2012-03-03 0:46 ` [PATCH 1/2] mmc: sdhci-s3c: Use CONFIG_PM_SLEEP to ifdef system suspend Mark Brown
2012-03-03 0:46 ` [PATCH 2/2] mmc: sdhci-s3c: Enable runtime power management Mark Brown
2012-03-05 10:48 ` Jaehoon Chung
2012-03-05 11:52 ` Mark Brown
2012-03-06 6:40 ` Jaehoon Chung
2012-03-09 4:57 ` Chris Ball
2012-03-09 5:08 ` Chris Ball
2012-03-09 12:26 ` Mark Brown
2012-03-05 10:24 ` [PATCH 1/2] mmc: sdhci-s3c: Use CONFIG_PM_SLEEP to ifdef system suspend Jaehoon Chung
2012-03-09 4:56 ` Chris Ball
2012-03-27 15:50 ` [PATCH v3 0/6] mmc: sdhci-s3c: Rework platform data and add device tree support Chris Ball
2012-03-28 9:54 ` Mark Brown
2012-03-29 3:15 ` Kukjin Kim
2012-04-01 1:12 ` Chris Ball
2012-04-02 19:08 ` Kukjin Kim
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1328032576-9269-2-git-send-email-thomas.abraham@linaro.org \
--to=thomas.abraham@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).