From 0dee18d8172e158b173825a09bf0523bae674ece Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Thu, 14 May 2015 11:48:40 +0100 Subject: [PATCH] bcm2835-sdhost: 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 sdhost interface is restricted to integer divisions of core_freq, and the highest sensible option for a core_freq of 250MHz is 84 (250/3 = 83.3MHz), the next being 125 (250/2) which is much too high. Use at your own risk. --- arch/arm/boot/dts/sdhost-overlay.dts | 6 ++++-- drivers/mmc/host/bcm2835-sdhost.c | 17 +++++++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/sdhost-overlay.dts b/arch/arm/boot/dts/sdhost-overlay.dts index 33db96e571ab2..b2653e95b38de 100644 --- a/arch/arm/boot/dts/sdhost-overlay.dts +++ b/arch/arm/boot/dts/sdhost-overlay.dts @@ -13,14 +13,15 @@ sdhost: sdhost@7e202000 { compatible = "brcm,bcm2835-sdhost"; reg = <0x7e202000 0x100>; + pinctrl-names = "default"; + pinctrl-0 = <&sdhost_pins>; interrupts = <2 24>; clocks = <&clk_sdhost>; dmas = <&dma 13>, <&dma 13>; dma-names = "tx", "rx"; brcm,delay-after-stop = <0>; - pinctrl-names = "default"; - pinctrl-0 = <&sdhost_pins>; + brcm,overclock-50 = <0>; status = "okay"; }; @@ -67,6 +68,7 @@ __overrides__ { delay_after_stop = <&sdhost>,"brcm,delay-after-stop:0"; + overclock_50 = <&sdhost>,"brcm,overclock-50:0"; force_pio = <&sdhost>,"brcm,force-pio?"; sdhost_freq = <&clk_sdhost>,"clock-frequency:0"; }; diff --git a/drivers/mmc/host/bcm2835-sdhost.c b/drivers/mmc/host/bcm2835-sdhost.c index 542ae120b812b..2a9eb9f7f87d4 100644 --- a/drivers/mmc/host/bcm2835-sdhost.c +++ b/drivers/mmc/host/bcm2835-sdhost.c @@ -184,6 +184,7 @@ struct bcm2835_host { int max_delay; /* maximum length of time spent waiting */ struct timeval stop_time; /* when the last stop was issued */ u32 delay_after_stop; /* minimum time between stop and subsequent data transfer */ + u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ }; @@ -1223,6 +1224,10 @@ static irqreturn_t bcm2835_sdhost_thread_irq(int irq, void *dev_id) void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock) { int div = 0; /* Initialized for compiler warning */ + unsigned int input_clock = clock; + + if (host->overclock_50 && (clock == 50000000)) + clock = host->overclock_50 * 1000000; /* The SDCDIV register has 11 bits, and holds (div - 2). But in data mode the max is 50MHz wihout a minimum, and only the @@ -1266,13 +1271,18 @@ void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock) if (div > SDCDIV_MAX_CDIV) div = SDCDIV_MAX_CDIV; - host->mmc->actual_clock = host->max_clk / (div + 2); + clock = host->max_clk / (div + 2); + host->mmc->actual_clock = clock; + + if (clock > input_clock) + pr_warn("%s: Overclocking to %dHz\n", + mmc_hostname(host->mmc), clock); host->cdiv = div; bcm2835_sdhost_write(host, host->cdiv, SDCDIV); pr_debug(DRIVER_NAME ": clock=%d -> max_clk=%d, cdiv=%x (actual clock %d)\n", - clock, host->max_clk, host->cdiv, host->mmc->actual_clock); + input_clock, host->max_clk, host->cdiv, host->mmc->actual_clock); } static void bcm2835_sdhost_request(struct mmc_host *mmc, struct mmc_request *mrq) @@ -1572,6 +1582,9 @@ static int bcm2835_sdhost_probe(struct platform_device *pdev) of_property_read_u32(node, "brcm,delay-after-stop", &host->delay_after_stop); + of_property_read_u32(node, + "brcm,overclock-50", + &host->overclock_50); host->allow_dma = ALLOW_DMA && !of_property_read_bool(node, "brcm,force-pio"); }