diff options
Diffstat (limited to 'target/linux/brcm2708/patches-4.4/0222-bcm2835-sdhost-Precalc-divisors-and-overclocks.patch')
-rw-r--r-- | target/linux/brcm2708/patches-4.4/0222-bcm2835-sdhost-Precalc-divisors-and-overclocks.patch | 270 |
1 files changed, 0 insertions, 270 deletions
diff --git a/target/linux/brcm2708/patches-4.4/0222-bcm2835-sdhost-Precalc-divisors-and-overclocks.patch b/target/linux/brcm2708/patches-4.4/0222-bcm2835-sdhost-Precalc-divisors-and-overclocks.patch deleted file mode 100644 index a35c8b1e79..0000000000 --- a/target/linux/brcm2708/patches-4.4/0222-bcm2835-sdhost-Precalc-divisors-and-overclocks.patch +++ /dev/null @@ -1,270 +0,0 @@ -From 152daaa4a44dfa67ec4c975d0f3446b38fe047bd Mon Sep 17 00:00:00 2001 -From: Phil Elwell <phil@raspberrypi.org> -Date: Thu, 31 Mar 2016 15:44:53 +0100 -Subject: [PATCH] bcm2835-sdhost: Precalc divisors and overclocks - -Recalculating the clock divisors when the core clock changes is wasteful -and makes it harder to manage the overclock settings. Instead, -precalculate them and only report significant changes. - -Signed-off-by: Phil Elwell <phil@raspberrypi.org> ---- - drivers/mmc/host/bcm2835-sdhost.c | 152 ++++++++++++++++++++++---------------- - 1 file changed, 88 insertions(+), 64 deletions(-) - ---- a/drivers/mmc/host/bcm2835-sdhost.c -+++ b/drivers/mmc/host/bcm2835-sdhost.c -@@ -154,12 +154,15 @@ struct bcm2835_host { - u32 pio_timeout; /* In jiffies */ - - int clock; /* Current clock speed */ -+ int clocks[2]; - - bool slow_card; /* Force 11-bit divisor */ - - unsigned int max_clk; /* Max src clock freq */ -- unsigned int min_clk; /* Min src clock freq */ -- unsigned int cur_clk; /* Current src clock freq */ -+ unsigned int src_clks[2]; /* Min/max src clock freqs */ -+ unsigned int cur_clk_idx; /* Index of current clock */ -+ unsigned int next_clk_idx; /* Next clock index */ -+ unsigned int cdivs[2]; - - struct tasklet_struct finish_tasklet; /* Tasklet structures */ - -@@ -213,7 +216,7 @@ struct bcm2835_host { - u32 delay_after_stop; /* minimum time between stop and subsequent data transfer */ - u32 delay_after_this_stop; /* minimum time between this stop and subsequent data transfer */ - u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ -- u32 overclock; /* Current frequency if overclocked, else zero */ -+ u32 prev_overclock_50; - u32 pio_limit; /* Maximum block count for PIO (0 = always DMA) */ - - u32 sectors; /* Cached card size in sectors */ -@@ -1509,10 +1512,35 @@ static irqreturn_t bcm2835_sdhost_irq(in - return result; - } - -+static void bcm2835_sdhost_select_clock(struct bcm2835_host *host, int idx) -+{ -+ unsigned int clock = host->clocks[idx]; -+ unsigned int cdiv = host->cdivs[idx]; -+ -+ host->mmc->actual_clock = clock; -+ host->ns_per_fifo_word = (1000000000/clock) * -+ ((host->mmc->caps & MMC_CAP_4_BIT_DATA) ? 8 : 32); -+ -+ host->cdiv = cdiv; -+ bcm2835_sdhost_write(host, host->cdiv, SDCDIV); -+ -+ /* Set the timeout to 500ms */ -+ bcm2835_sdhost_write(host, clock/2, SDTOUT); -+ -+ host->cur_clk_idx = host->next_clk_idx = idx; -+ -+ if (host->debug) -+ pr_info("%s: clock=%d -> src_clk=%d, cdiv=%x (actual %d)\n", -+ mmc_hostname(host->mmc), host->clock, -+ host->src_clks[idx], host->cdiv, -+ host->mmc->actual_clock); -+} -+ - void bcm2835_sdhost_set_clock(struct bcm2835_host *host) - { - int div = 0; /* Initialized for compiler warning */ - unsigned int clock = host->clock; -+ int clk_idx; - - if (host->debug) - pr_info("%s: set_clock(%d)\n", mmc_hostname(host->mmc), clock); -@@ -1553,53 +1581,45 @@ void bcm2835_sdhost_set_clock(struct bcm - return; - } - -- div = host->cur_clk / clock; -- if (div < 2) -- div = 2; -- if ((host->cur_clk / div) > clock) -- div++; -- div -= 2; -- -- if (div > SDCDIV_MAX_CDIV) -- div = SDCDIV_MAX_CDIV; -- -- clock = host->cur_clk / (div + 2); -- host->mmc->actual_clock = clock; -- -- /* Calibrate some delays */ -- -- host->ns_per_fifo_word = (1000000000/clock) * -- ((host->mmc->caps & MMC_CAP_4_BIT_DATA) ? 8 : 32); -+ /* Calculate the clock divisors */ -+ for (clk_idx = 0; clk_idx <= host->variable_clock; clk_idx++) -+ { -+ unsigned int cur_clk = host->src_clks[clk_idx]; -+ unsigned int actual_clock; - -- if (clock > host->clock) { -- /* Save the closest value, to make it easier -- to reduce in the event of error */ -- host->overclock_50 = (clock/MHZ); -- -- if (clock != host->overclock) { -- pr_warn("%s: overclocking to %dHz\n", -- mmc_hostname(host->mmc), clock); -- host->overclock = clock; -+ div = cur_clk / clock; -+ if (div < 2) -+ div = 2; -+ if ((cur_clk / div) > clock) -+ div++; -+ div -= 2; -+ -+ if (div > SDCDIV_MAX_CDIV) -+ div = SDCDIV_MAX_CDIV; -+ actual_clock = cur_clk / (div + 2); -+ -+ host->cdivs[clk_idx] = div; -+ host->clocks[clk_idx] = actual_clock; -+ -+ if (host->overclock_50 != host->prev_overclock_50) { -+ const char *clk_name = ""; -+ if (host->variable_clock) -+ clk_name = clk_idx ? " (turbo)" : " (normal)"; -+ if (actual_clock > host->clock) -+ pr_info("%s: overclocking to %dHz%s\n", -+ mmc_hostname(host->mmc), -+ actual_clock, clk_name); -+ else if ((host->overclock_50 < 50) && (clk_idx == 0)) -+ pr_info("%s: cancelling overclock%s\n", -+ mmc_hostname(host->mmc), -+ host->variable_clock ? "s" : ""); - } - } -- else if (host->overclock) -- { -- host->overclock = 0; -- if (clock == 50 * MHZ) -- pr_warn("%s: cancelling overclock\n", -- mmc_hostname(host->mmc)); -- } - -- host->cdiv = div; -- bcm2835_sdhost_write(host, host->cdiv, SDCDIV); -+ if (host->clock == 50*MHZ) -+ host->prev_overclock_50 = host->overclock_50; - -- /* Set the timeout to 500ms */ -- bcm2835_sdhost_write(host, host->mmc->actual_clock/2, SDTOUT); -- -- if (host->debug) -- pr_info("%s: clock=%d -> cur_clk=%d, cdiv=%x (actual clock %d)\n", -- mmc_hostname(host->mmc), host->clock, -- host->cur_clk, host->cdiv, host->mmc->actual_clock); -+ bcm2835_sdhost_select_clock(host, host->cur_clk_idx); - } - - static void bcm2835_sdhost_request(struct mmc_host *mmc, struct mmc_request *mrq) -@@ -1657,6 +1677,9 @@ static void bcm2835_sdhost_request(struc - - spin_lock_irqsave(&host->lock, flags); - -+ if (host->next_clk_idx != host->cur_clk_idx) -+ bcm2835_sdhost_select_clock(host, host->next_clk_idx); -+ - WARN_ON(host->mrq != NULL); - host->mrq = mrq; - -@@ -1719,11 +1742,7 @@ static int bcm2835_sdhost_cpufreq_callba - return NOTIFY_BAD; - break; - case CPUFREQ_POSTCHANGE: -- if (freq->new > freq->old) -- host->cur_clk = host->max_clk; -- else -- host->cur_clk = host->min_clk; -- bcm2835_sdhost_set_clock(host); -+ host->next_clk_idx = (freq->new > freq->old); - up(&host->cpufreq_semaphore); - break; - default: -@@ -1763,8 +1782,11 @@ static void bcm2835_sdhost_set_ios(struc - ios->clock, ios->power_mode, ios->bus_width, - ios->timing, ios->signal_voltage, ios->drv_type); - -- if (ios->clock && !host->cur_clk) -- host->cur_clk = get_core_clock(RPI_FIRMWARE_GET_CLOCK_RATE); -+ if (ios->clock && (host->cur_clk_idx == -1)) { -+ unsigned int cur_clk = -+ get_core_clock(RPI_FIRMWARE_GET_CLOCK_RATE); -+ host->cur_clk_idx = (cur_clk == host->src_clks[0]) ? 0 : 1; -+ } - - spin_lock_irqsave(&host->lock, flags); - -@@ -1854,11 +1876,12 @@ static void bcm2835_sdhost_tasklet_finis - - /* Drop the overclock after any data corruption, or after any - error overclocked */ -- if (host->overclock) { -+ if (host->clock > 50*MHZ) { - if ((mrq->cmd && mrq->cmd->error) || - (mrq->data && mrq->data->error) || - (mrq->stop && mrq->stop->error)) { -- host->overclock_50--; -+ host->overclock_50 = (host->clock/MHZ) - 1; -+ - pr_warn("%s: reducing overclock due to errors\n", - mmc_hostname(host->mmc)); - bcm2835_sdhost_set_clock(host); -@@ -2022,7 +2045,7 @@ static int bcm2835_sdhost_probe(struct p - struct bcm2835_host *host; - struct mmc_host *mmc; - const __be32 *addr; -- unsigned int max_clk; -+ unsigned int max_clk, min_clk; - int ret; - - pr_debug("bcm2835_sdhost_probe\n"); -@@ -2128,12 +2151,8 @@ static int bcm2835_sdhost_probe(struct p - else - mmc->caps |= MMC_CAP_4_BIT_DATA; - -- ret = bcm2835_sdhost_add_host(host); -- if (ret) -- goto err; -- - /* Query the core clock frequencies */ -- host->min_clk = get_core_clock(RPI_FIRMWARE_GET_MIN_CLOCK_RATE); -+ min_clk = get_core_clock(RPI_FIRMWARE_GET_MIN_CLOCK_RATE); - max_clk = get_core_clock(RPI_FIRMWARE_GET_MAX_CLOCK_RATE); - if (max_clk != host->max_clk) { - pr_warn("%s: Expected max clock %d, found %d\n", -@@ -2141,19 +2160,24 @@ static int bcm2835_sdhost_probe(struct p - host->max_clk = max_clk; - } - -- if (host->min_clk != host->max_clk) { -+ host->src_clks[0] = min_clk; -+ host->cur_clk_idx = -1; -+ if (max_clk != min_clk) { -+ host->src_clks[1] = max_clk; - host->cpufreq_nb.notifier_call = - bcm2835_sdhost_cpufreq_callback; - sema_init(&host->cpufreq_semaphore, 1); - cpufreq_register_notifier(&host->cpufreq_nb, - CPUFREQ_TRANSITION_NOTIFIER); - host->variable_clock = 1; -- host->cur_clk = 0; /* Get this later */ - } else { - host->variable_clock = 0; -- host->cur_clk = host->max_clk; - } - -+ ret = bcm2835_sdhost_add_host(host); -+ if (ret) -+ goto err; -+ - platform_set_drvdata(pdev, host); - - pr_debug("bcm2835_sdhost_probe -> OK\n"); |