From 7a7ebd4523817db4e59801250be07f3c0751a43b Mon Sep 17 00:00:00 2001 From: Alex Frid Date: Fri, 4 Aug 2017 18:47:16 -0700 Subject: [PATCH] clk: soc: tegra: Add DFLL tune high margin voltage Added DFLL tune high margin voltage entry in CVB table. This allows to replace current fixed margin defined as number of DFLL voltage steps with per-table/per-chip margin in millivolts, and convert it to steps during DFLL initialization. Bug 1967884 Change-Id: I56268ae2faf9cc633b9f988cacbfd0ea3ba77ff3 Signed-off-by: Alex Frid Reviewed-on: https://git-master.nvidia.com/r/1576307 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/clk/tegra/clk-dfll.c | 42 +++++++++++++++++++--- drivers/clk/tegra/clk-dfll.h | 2 ++ drivers/clk/tegra/clk-tegra124-dfll-fcpu.c | 4 +++ drivers/clk/tegra/cvb.h | 1 + 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c index 9b7d731fa9e6..4ab614ef1bc0 100644 --- a/drivers/clk/tegra/clk-dfll.c +++ b/drivers/clk/tegra/clk-dfll.c @@ -886,10 +886,10 @@ static void dfll_load_i2c_lut(struct tegra_dfll *td) u32 val; for (i = 0; i < MAX_DFLL_VOLTAGES; i++) { - if (i < td->lut_min) - lut_index = td->lut_min; - else if (i > td->lut_max) - lut_index = td->lut_max; + if (i < td->lut_bottom) + lut_index = td->lut_bottom; + else if (i > td->lut_size - 1) + lut_index = td->lut_size - 1; else lut_index = i; @@ -1020,6 +1020,28 @@ static int find_lut_index_for_rate(struct tegra_dfll *td, unsigned long rate) return -ENOENT; } +/** + * find_mv_out_cap - find the out_map index with voltage >= @mv + * @td: DFLL instance + * @mv: millivolts + * + * Find the lut index with voltage greater than or equal to @mv, + * and return it. If all of the voltages in out_map are less than + * @mv, then return the lut index * corresponding to the highest + * possible voltage, even though it's less than @mv. + */ +static u8 find_mv_out_cap(struct tegra_dfll *td, int mv) +{ + u8 i; + + for (i = td->lut_bottom; i < td->lut_size; i++) { + if (td->lut_uv[i] >= mv * 1000) + return i; + } + + return i - 1; /* maximum possible output */ +} + /** * dfll_calculate_rate_request - calculate DFLL parameters for a given rate * @td: DFLL instance @@ -1704,7 +1726,17 @@ static void dfll_init_tuning_thresholds(struct tegra_dfll *td) if ((out_min + 2) > max_voltage_index) return; - out_start = out_min + DFLL_TUNE_HIGH_MARGIN_STEPS; + if (td->soc->cvb->cpu_dfll_data.tune_high_margin_millivolts) { + unsigned int mv; + + mv = td->soc->tune_high_min_millivolts + + td->soc->cvb->cpu_dfll_data.tune_high_margin_millivolts; + if (mv * 1000 > td->lut_uv[max_voltage_index]) + return; + out_start = max((u8)(out_min + 1), find_mv_out_cap(td, mv)); + } else { + out_start = out_min + DFLL_TUNE_HIGH_MARGIN_STEPS; + } if (out_start > max_voltage_index) return; diff --git a/drivers/clk/tegra/clk-dfll.h b/drivers/clk/tegra/clk-dfll.h index fb209eb5f365..f05d14cd6d44 100644 --- a/drivers/clk/tegra/clk-dfll.h +++ b/drivers/clk/tegra/clk-dfll.h @@ -31,6 +31,8 @@ struct tegra_dfll_soc_data { unsigned long max_freq; const struct cvb_table *cvb; struct rail_alignment alignment; + unsigned int min_millivolts; + unsigned int tune_high_min_millivolts; void (*init_clock_trimmers)(void); void (*set_clock_trimmers_high)(void); diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c index a507b1622995..d801589b35cb 100644 --- a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c +++ b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c @@ -685,6 +685,7 @@ static struct cvb_table tegra210b01_cpu_cvb_tables[] = { .tune1_low = 0x012207ff, .tune1_high = 0x03FFF7FF, .tune_high_min_millivolts = 850, + .tune_high_margin_millivolts = 38, } }, { @@ -697,6 +698,7 @@ static struct cvb_table tegra210b01_cpu_cvb_tables[] = { .tune0_high = 0x0000ffff, .tune1_low = 0x021107ff, .tune_high_min_millivolts = 850, + .tune_high_margin_millivolts = 38, } }, { @@ -709,6 +711,7 @@ static struct cvb_table tegra210b01_cpu_cvb_tables[] = { .tune0_high = 0x0000ffff, .tune1_low = 0x021107ff, .tune_high_min_millivolts = 850, + .tune_high_margin_millivolts = 38, } }, { @@ -720,6 +723,7 @@ static struct cvb_table tegra210b01_cpu_cvb_tables[] = { .tune0_low = 0x0000ffcf, .tune1_low = 0x012207ff, .tune_high_min_millivolts = 850, + .tune_high_margin_millivolts = 38, } }, }; diff --git a/drivers/clk/tegra/cvb.h b/drivers/clk/tegra/cvb.h index 95694e4199f6..244b771061db 100644 --- a/drivers/clk/tegra/cvb.h +++ b/drivers/clk/tegra/cvb.h @@ -34,6 +34,7 @@ struct cvb_cpu_dfll_data { u32 tune1_low; u32 tune1_high; unsigned int tune_high_min_millivolts; + unsigned int tune_high_margin_millivolts; }; struct cvb_table {