summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Elwell <phil@raspberrypi.org>2015-05-14 11:55:57 +0100
committerpopcornmix <popcornmix@gmail.com>2015-05-18 14:13:23 +0100
commit44fa0c9f4fcf3519aa91175f13f41d3744e6dc29 (patch)
tree6d5f2e1e4eec9deab39c6e75e7c261c7d33e165a
parent628d654d5aa2d845926402a1b83fa2822a83cee7 (diff)
downloadlinux-44fa0c9f4fcf3519aa91175f13f41d3744e6dc29.tar.gz
bcm2835-mmc: Adding overclocking option
Allow a different clock speed to be substitued for a requested 50MHz. This option is exposed using the "overclock_50" DT parameter. Note that the mmc interface is restricted to EVEN integer divisions of 250MHz, and the highest sensible option is 63 (250/4 = 62.5), the next being 125 (250/2) which is much too high. Use at your own risk.
-rw-r--r--arch/arm/boot/dts/mmc-overlay.dts11
-rw-r--r--drivers/mmc/host/bcm2835-mmc.c25
2 files changed, 33 insertions, 3 deletions
diff --git a/arch/arm/boot/dts/mmc-overlay.dts b/arch/arm/boot/dts/mmc-overlay.dts
new file mode 100644
index 000000000000..3d28041d61f1
--- /dev/null
+++ b/arch/arm/boot/dts/mmc-overlay.dts
@@ -0,0 +1,11 @@
+/dts-v1/;
+/plugin/;
+
+/{
+ compatible = "brcm,bcm2708";
+
+ __overrides__ {
+ overclock_50 = <&mmc>,"brcm,overclock-50:0";
+ force_pio = <&mmc>,"brcm,force-pio?";
+ };
+};
diff --git a/drivers/mmc/host/bcm2835-mmc.c b/drivers/mmc/host/bcm2835-mmc.c
index 68314d599d30..c7c2ca1b0271 100644
--- a/drivers/mmc/host/bcm2835-mmc.c
+++ b/drivers/mmc/host/bcm2835-mmc.c
@@ -131,6 +131,8 @@ struct bcm2835_host {
#define SDHCI_AUTO_CMD12 (1<<6) /* Auto CMD12 support */
#define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */
#define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */
+
+ u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */
};
@@ -1086,7 +1088,10 @@ void bcm2835_mmc_set_clock(struct bcm2835_host *host, unsigned int clock)
int real_div = div, clk_mul = 1;
u16 clk = 0;
unsigned long timeout;
+ unsigned int input_clock = clock;
+ if (host->overclock_50 && (clock == 50000000))
+ clock = host->overclock_50 * 1000000;
host->mmc->actual_clock = 0;
@@ -1110,7 +1115,12 @@ void bcm2835_mmc_set_clock(struct bcm2835_host *host, unsigned int clock)
div >>= 1;
if (real_div)
- host->mmc->actual_clock = (host->max_clk * clk_mul) / real_div;
+ clock = (host->max_clk * clk_mul) / real_div;
+ host->mmc->actual_clock = clock;
+
+ if (clock > input_clock)
+ pr_warn("%s: Overclocking to %dHz\n",
+ mmc_hostname(host->mmc), clock);
clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT;
clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN)
@@ -1177,6 +1187,9 @@ static void bcm2835_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
u8 ctrl;
u16 clk, ctrl_2;
+ pr_debug("bcm2835_mmc_set_ios: clock %d, pwr %d, bus_width %d, timing %d, vdd %d, drv_type %d\n",
+ ios->clock, ios->power_mode, ios->bus_width,
+ ios->timing, ios->signal_voltage, ios->drv_type);
spin_lock_irqsave(&host->lock, flags);
@@ -1444,10 +1457,16 @@ static int bcm2835_mmc_probe(struct platform_device *pdev)
goto err;
}
- if (node)
+ if (node) {
mmc_of_parse(mmc);
- else
+
+ /* Read any custom properties */
+ of_property_read_u32(node,
+ "brcm,overclock-50",
+ &host->overclock_50);
+ } else {
mmc->caps |= MMC_CAP_4_BIT_DATA;
+ }
ret = bcm2835_mmc_add_host(host);
if (ret)