mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-07 02:19:54 +00:00
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.
This commit is contained in:
@@ -13,14 +13,15 @@
|
|||||||
sdhost: sdhost@7e202000 {
|
sdhost: sdhost@7e202000 {
|
||||||
compatible = "brcm,bcm2835-sdhost";
|
compatible = "brcm,bcm2835-sdhost";
|
||||||
reg = <0x7e202000 0x100>;
|
reg = <0x7e202000 0x100>;
|
||||||
|
pinctrl-names = "default";
|
||||||
|
pinctrl-0 = <&sdhost_pins>;
|
||||||
interrupts = <2 24>;
|
interrupts = <2 24>;
|
||||||
clocks = <&clk_sdhost>;
|
clocks = <&clk_sdhost>;
|
||||||
dmas = <&dma 13>,
|
dmas = <&dma 13>,
|
||||||
<&dma 13>;
|
<&dma 13>;
|
||||||
dma-names = "tx", "rx";
|
dma-names = "tx", "rx";
|
||||||
brcm,delay-after-stop = <0>;
|
brcm,delay-after-stop = <0>;
|
||||||
pinctrl-names = "default";
|
brcm,overclock-50 = <0>;
|
||||||
pinctrl-0 = <&sdhost_pins>;
|
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -67,6 +68,7 @@
|
|||||||
|
|
||||||
__overrides__ {
|
__overrides__ {
|
||||||
delay_after_stop = <&sdhost>,"brcm,delay-after-stop:0";
|
delay_after_stop = <&sdhost>,"brcm,delay-after-stop:0";
|
||||||
|
overclock_50 = <&sdhost>,"brcm,overclock-50:0";
|
||||||
force_pio = <&sdhost>,"brcm,force-pio?";
|
force_pio = <&sdhost>,"brcm,force-pio?";
|
||||||
sdhost_freq = <&clk_sdhost>,"clock-frequency:0";
|
sdhost_freq = <&clk_sdhost>,"clock-frequency:0";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -184,6 +184,7 @@ struct bcm2835_host {
|
|||||||
int max_delay; /* maximum length of time spent waiting */
|
int max_delay; /* maximum length of time spent waiting */
|
||||||
struct timeval stop_time; /* when the last stop was issued */
|
struct timeval stop_time; /* when the last stop was issued */
|
||||||
u32 delay_after_stop; /* minimum time between stop and subsequent data transfer */
|
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)
|
void bcm2835_sdhost_set_clock(struct bcm2835_host *host, unsigned int clock)
|
||||||
{
|
{
|
||||||
int div = 0; /* Initialized for compiler warning */
|
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).
|
/* The SDCDIV register has 11 bits, and holds (div - 2).
|
||||||
But in data mode the max is 50MHz wihout a minimum, and only the
|
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)
|
if (div > SDCDIV_MAX_CDIV)
|
||||||
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;
|
host->cdiv = div;
|
||||||
bcm2835_sdhost_write(host, host->cdiv, SDCDIV);
|
bcm2835_sdhost_write(host, host->cdiv, SDCDIV);
|
||||||
|
|
||||||
pr_debug(DRIVER_NAME ": clock=%d -> max_clk=%d, cdiv=%x (actual clock %d)\n",
|
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)
|
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,
|
of_property_read_u32(node,
|
||||||
"brcm,delay-after-stop",
|
"brcm,delay-after-stop",
|
||||||
&host->delay_after_stop);
|
&host->delay_after_stop);
|
||||||
|
of_property_read_u32(node,
|
||||||
|
"brcm,overclock-50",
|
||||||
|
&host->overclock_50);
|
||||||
host->allow_dma = ALLOW_DMA &&
|
host->allow_dma = ALLOW_DMA &&
|
||||||
!of_property_read_bool(node, "brcm,force-pio");
|
!of_property_read_bool(node, "brcm,force-pio");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user