From 96f9902ff40b2124fbe34eeac727c596e7701702 Mon Sep 17 00:00:00 2001
From: Andy Green <andy@openmoko.com>
Date: Fri, 25 Jul 2008 23:06:20 +0100
Subject: [PATCH] add-limit-sdcard-clk-cmdline.patch

This patch allows you to control the maximum clock rate that will
be selected for SD Card access, from the kernel commandline using

 glamo_mci.sd_max_clk=10000000

and also from

 echo 10000000 > /sys/module/glamo_mci/parameters/sd_max_clk

although you have to suspend and resume to make the limit operational
on the actual SD_CLK line.

Clocks that are possible are divided down from ~50MHz, so 25000000,
16666666, 12500000, 10000000, etc.  With Freerunner A5 revision that
has 100R series resistors in SD Card signals, I didn't get reliable
operation above 16MHz.  With A6 revision the series resistors went
down to 75R, maybe it can work at 25MHz.

Reducing the clock rate is something to try if you find that your
SD Card is not communicating properly with the default speed.

Signed-off-by: Andy Green <andy@openmoko.com>
---
 drivers/mfd/glamo/glamo-mci.c |   38 +++++++++++++++++++++++++++++---------
 1 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/drivers/mfd/glamo/glamo-mci.c b/drivers/mfd/glamo/glamo-mci.c
index b53827e..67bb815 100644
--- a/drivers/mfd/glamo/glamo-mci.c
+++ b/drivers/mfd/glamo/glamo-mci.c
@@ -40,6 +40,24 @@ static spinlock_t clock_lock;
 
 static void glamo_mci_send_request(struct mmc_host *mmc);
 
+/*
+ * Max SD clock rate
+ *
+ * held at /(3 + 1) due to concerns of 100R recommended series resistor
+ * allows 16MHz @ 4-bit --> 8MBytes/sec raw
+ *
+ * you can override this on kernel commandline using
+ *
+ *   glamo_mci.sd_max_clk=10000000
+ *
+ * for example
+ */
+
+static int sd_max_clk = 50000000 / 3;
+module_param(sd_max_clk, int, 0644);
+
+
+
 unsigned char CRC7(u8 * pu8, int cnt)
 {
 	u8 crc = 0;
@@ -676,9 +694,9 @@ static void glamo_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	    (ios->power_mode == MMC_POWER_UP)) {
 		dev_info(&host->pdev->dev,
 			"powered (vdd = %d) clk: %lukHz div=%d (req: %ukHz). "
-			"Bus width=%d\n",ios->vdd,
-			host->real_rate / 1000, host->real_rate,
-			ios->clock / 1000, ios->bus_width);
+			"Bus width=%d\n",(int)ios->vdd,
+			host->real_rate / 1000, (int)host->clk_div,
+			ios->clock / 1000, (int)ios->bus_width);
 	} else
 		dev_info(&host->pdev->dev, "glamo_mci_set_ios: power down.\n");
 
@@ -800,11 +818,7 @@ static int glamo_mci_probe(struct platform_device *pdev)
 			  MMC_CAP_MMC_HIGHSPEED |
 			  MMC_CAP_SD_HIGHSPEED;
 	mmc->f_min 	= host->clk_rate / 256;
-	/*
-	 * held at /4 due to concerns of 100R recommended series resistor
-	 * allows 16MHz @ 4-bit --> 8MBytes/sec raw
-	 */
-	mmc->f_max 	= host->clk_rate / 3;
+	mmc->f_max 	= sd_max_clk;
 
 	mmc->max_blk_count	= (1 << 16) - 1; /* GLAMO_REG_MMC_RB_BLKCNT */
 	mmc->max_blk_size	= (1 << 12) - 1; /* GLAMO_REG_MMC_RB_BLKLEN */
@@ -866,12 +880,18 @@ static int glamo_mci_suspend(struct platform_device *dev, pm_message_t state)
 {
 	struct mmc_host *mmc = platform_get_drvdata(dev);
 	struct glamo_mci_host 	*host = mmc_priv(mmc);
+	int ret;
 
 	host->suspending++;
 	if (host->pdata->mci_all_dependencies_resumed)
 		(host->pdata->mci_suspending)(dev);
 
-	return mmc_suspend_host(mmc, state);
+	ret = mmc_suspend_host(mmc, state);
+
+	/* so that when we resume, we use any modified max rate */
+	mmc->f_max = sd_max_clk;
+
+	return ret;
 }
 
 int glamo_mci_resume(struct platform_device *dev)
-- 
1.5.6.3