diff options
author | Alex Frid <afrid@nvidia.com> | 2014-09-21 00:28:51 -0400 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2015-03-18 15:11:28 -0400 |
commit | 3a81ed7e979343df35d65279fb101cbb5f0ccfc7 (patch) | |
tree | 1302b025e5d2668503eccb47c915f5982eaa20bd /drivers/gpu/nvgpu/gm20b | |
parent | 270029a760303443caaf2deb2c74cad67bbb7709 (diff) |
gpu: nvgpu: Change GPCPLL NA rate in flight
Added support for GM20b GPCPLL frequency change in NA mode outside of
bypass. In this case the respective PLL DVFS detection settings are
updated in flight. The implemented algorithm relies on characterization
providing two frequency limits at the same voltage: max frequency on
the F/V curve (Fmax@V) in NA mode with characterized DVFS coefficient,
and safe frequency under the curve when DVFS coefficient is zero
(Fsafe@V, which is effectively the same as Fmax@V in legacy/non-DVFS
mode).
Transition between two Fmax@V points on the curve includes:
- Lowering frequency to Fsafe@V for the minimum V of the transition
end-points
- Setting DVFS coefficient to zero
- Changing DVFS calibration point to the new voltage
- Setting DVFS coefficient characterized for the new voltage
- Setting final target frequency
Note that voltage is changed by Tegra SoC DVFS before (when voltage
increases), or after (whet voltage decreases) the above procedure.
This commit kept NA mode disabled.
Bug 1555318
Change-Id: Ib5620aaa113dc1caa69ecd402d9c6f68e39c472c
Signed-off-by: Alex Frid <afrid@nvidia.com>
Reviewed-on: http://git-master/r/501042
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gm20b')
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/clk_gm20b.c | 121 |
1 files changed, 115 insertions, 6 deletions
diff --git a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c index adf5136a..b1d1af4d 100644 --- a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c | |||
@@ -43,6 +43,10 @@ | |||
43 | #define BOOT_GPU_UV 1000000 /* gpu rail boot voltage 1.0V */ | 43 | #define BOOT_GPU_UV 1000000 /* gpu rail boot voltage 1.0V */ |
44 | #define ADC_SLOPE_UV 10000 /* default ADC detection slope 10mV */ | 44 | #define ADC_SLOPE_UV 10000 /* default ADC detection slope 10mV */ |
45 | 45 | ||
46 | /* FIXME: need characterized safe margin constant or table, and minimum */ | ||
47 | #define DVFS_SAFE_MARGIN (2*38400) | ||
48 | #define DVFS_SAFE_MIN_FREQ (2*307200) | ||
49 | |||
46 | static struct pll_parms gpc_pll_params = { | 50 | static struct pll_parms gpc_pll_params = { |
47 | 128000, 2600000, /* freq */ | 51 | 128000, 2600000, /* freq */ |
48 | 1300000, 2600000, /* vco */ | 52 | 1300000, 2600000, /* vco */ |
@@ -222,7 +226,7 @@ found_match: | |||
222 | 226 | ||
223 | *target_freq = pll->freq; | 227 | *target_freq = pll->freq; |
224 | 228 | ||
225 | gk20a_dbg_clk("actual target freq %d MHz, M %d, N %d, PL %d(div%d)", | 229 | gk20a_dbg_clk("actual target freq %d kHz, M %d, N %d, PL %d(div%d)", |
226 | *target_freq, pll->M, pll->N, pll->PL, pl_to_div(pll->PL)); | 230 | *target_freq, pll->M, pll->N, pll->PL, pl_to_div(pll->PL)); |
227 | 231 | ||
228 | gk20a_dbg_fn("done"); | 232 | gk20a_dbg_fn("done"); |
@@ -743,7 +747,14 @@ pll_locked: | |||
743 | return 0; | 747 | return 0; |
744 | } | 748 | } |
745 | 749 | ||
746 | /* GPCPLL programming in legacy (non-DVFS) mode */ | 750 | /* |
751 | * Change GPCPLL frequency: | ||
752 | * - in legacy (non-DVFS) mode | ||
753 | * - in DVFS mode at constant DVFS detection settings, matching current/lower | ||
754 | * voltage; the same procedure can be used in this case, since maximum DVFS | ||
755 | * detection limit makes sure that PLL output remains under F/V curve when | ||
756 | * voltage increases arbitrary. | ||
757 | */ | ||
747 | static int clk_program_gpc_pll(struct gk20a *g, struct pll *gpll_new, | 758 | static int clk_program_gpc_pll(struct gk20a *g, struct pll *gpll_new, |
748 | int allow_slide) | 759 | int allow_slide) |
749 | { | 760 | { |
@@ -868,17 +879,115 @@ set_pldiv: | |||
868 | return clk_slide_gpc_pll(g, gpll_new); | 879 | return clk_slide_gpc_pll(g, gpll_new); |
869 | } | 880 | } |
870 | 881 | ||
871 | /* GPCPLL programming in DVFS mode */ | 882 | /* Find GPCPLL config safe at DVFS coefficient = 0, matching target frequency */ |
883 | static void clk_config_pll_safe_dvfs(struct gk20a *g, struct pll *gpll) | ||
884 | { | ||
885 | u32 nsafe, nmin; | ||
886 | |||
887 | if (gpll->freq > DVFS_SAFE_MIN_FREQ) | ||
888 | gpll->freq -= DVFS_SAFE_MARGIN; | ||
889 | |||
890 | nmin = DIV_ROUND_UP(gpll->M * gpc_pll_params.min_vco, gpll->clk_in); | ||
891 | nsafe = gpll->M * gpll->freq / gpll->clk_in; | ||
892 | |||
893 | /* | ||
894 | * If safe frequency is above VCOmin, it can be used in safe PLL config | ||
895 | * as is. Since safe frequency is below both old and new frequencies, | ||
896 | * in this case all three configurations have same post divider 1:1, and | ||
897 | * direct old=>safe=>new n-sliding will be used for transitions. | ||
898 | * | ||
899 | * Otherwise, if safe frequency is below VCO min, post-divider in safe | ||
900 | * configuration (and possibly in old and/or new configurations) is | ||
901 | * above 1:1, and each old=>safe and safe=>new transitions includes | ||
902 | * sliding to/from VCOmin, as well as divider changes. To avoid extra | ||
903 | * dynamic ramps from VCOmin during old=>safe transition and to VCOmin | ||
904 | * during safe=>new transition, select nmin as safe NDIV, and set safe | ||
905 | * post divider to assure PLL output is below safe frequency | ||
906 | */ | ||
907 | if (nsafe < nmin) { | ||
908 | gpll->PL = DIV_ROUND_UP(nmin * gpll->clk_in, | ||
909 | gpll->M * gpll->freq); | ||
910 | nsafe = nmin; | ||
911 | } | ||
912 | gpll->N = nsafe; | ||
913 | clk_config_dvfs_ndiv(gpll->dvfs.mv, gpll->N, &gpll->dvfs); | ||
914 | |||
915 | gk20a_dbg_clk("safe freq %d kHz, M %d, N %d, PL %d(div%d)", | ||
916 | gpll->freq, gpll->M, gpll->N, gpll->PL, pl_to_div(gpll->PL)); | ||
917 | } | ||
918 | |||
919 | /* Change GPCPLL frequency and DVFS detection settings in DVFS mode */ | ||
872 | static int clk_program_na_gpc_pll(struct gk20a *g, struct pll *gpll_new, | 920 | static int clk_program_na_gpc_pll(struct gk20a *g, struct pll *gpll_new, |
873 | int allow_slide) | 921 | int allow_slide) |
874 | { | 922 | { |
923 | int ret; | ||
924 | struct pll gpll_safe; | ||
925 | struct pll *gpll_old = &g->clk.gpc_pll_last; | ||
926 | |||
927 | BUG_ON(gpll_new->M != 1); /* the only MDIV in NA mode */ | ||
875 | clk_config_dvfs(g, gpll_new); | 928 | clk_config_dvfs(g, gpll_new); |
876 | 929 | ||
877 | if (!gpll_new->enabled) | 930 | /* |
931 | * In cases below no intermediate steps in PLL DVFS configuration are | ||
932 | * necessary because either | ||
933 | * - PLL DVFS will be configured under bypass directly to target, or | ||
934 | * - voltage is not changing, so DVFS detection settings are the same | ||
935 | */ | ||
936 | if (!allow_slide || !gpll_new->enabled || | ||
937 | (gpll_old->dvfs.mv == gpll_new->dvfs.mv)) | ||
878 | return clk_program_gpc_pll(g, gpll_new, allow_slide); | 938 | return clk_program_gpc_pll(g, gpll_new, allow_slide); |
879 | 939 | ||
880 | /* always under bypass, for now */ | 940 | /* |
881 | return clk_program_gpc_pll(g, gpll_new, 0); | 941 | * Interim step for changing DVFS detection settings: low enough |
942 | * frequency to be safe at at DVFS coeff = 0. | ||
943 | * | ||
944 | * 1. If voltage is increasing: | ||
945 | * - safe frequency target matches the lowest - old - frequency | ||
946 | * - DVFS settings are still old | ||
947 | * - Voltage already increased to new level by tegra DVFS, but maximum | ||
948 | * detection limit assures PLL output remains under F/V curve | ||
949 | * | ||
950 | * 2. If voltage is decreasing: | ||
951 | * - safe frequency target matches the lowest - new - frequency | ||
952 | * - DVFS settings are still old | ||
953 | * - Voltage is also old, it will be lowered by tegra DVFS afterwards | ||
954 | * | ||
955 | * Interim step can be skipped if old frequency is below safe minimum, | ||
956 | * i.e., it is low enough to be safe at any voltage in operating range | ||
957 | * with zero DVFS coefficient. | ||
958 | */ | ||
959 | if (gpll_old->freq > DVFS_SAFE_MIN_FREQ) { | ||
960 | if (gpll_old->dvfs.mv < gpll_new->dvfs.mv) { | ||
961 | gpll_safe = *gpll_old; | ||
962 | gpll_safe.dvfs.mv = gpll_new->dvfs.mv; | ||
963 | } else { | ||
964 | gpll_safe = *gpll_new; | ||
965 | gpll_safe.dvfs = gpll_old->dvfs; | ||
966 | } | ||
967 | clk_config_pll_safe_dvfs(g, &gpll_safe); | ||
968 | |||
969 | ret = clk_program_gpc_pll(g, &gpll_safe, 1); | ||
970 | if (ret) { | ||
971 | gk20a_err(dev_from_gk20a(g), "Safe dvfs program fail\n"); | ||
972 | return ret; | ||
973 | } | ||
974 | } | ||
975 | |||
976 | /* | ||
977 | * DVFS detection settings transition: | ||
978 | * - Set DVFS coefficient zero (safe, since already at frequency safe | ||
979 | * at DVFS coeff = 0 for the lowest of the old/new end-points) | ||
980 | * - Set calibration level to new voltage (safe, since DVFS coeff = 0) | ||
981 | * - Set DVFS coefficient to match new voltage (safe, since already at | ||
982 | * frequency safe at DVFS coeff = 0 for the lowest of the old/new | ||
983 | * end-points. | ||
984 | */ | ||
985 | clk_set_dfs_coeff(g, 0); | ||
986 | clk_set_dfs_ext_cal(g, gpll_new->dvfs.dfs_ext_cal); | ||
987 | clk_set_dfs_coeff(g, gpll_new->dvfs.dfs_coeff); | ||
988 | |||
989 | /* Finally set target rate (with DVFS detection settings already new) */ | ||
990 | return clk_program_gpc_pll(g, gpll_new, 1); | ||
882 | } | 991 | } |
883 | 992 | ||
884 | static int clk_disable_gpcpll(struct gk20a *g, int allow_slide) | 993 | static int clk_disable_gpcpll(struct gk20a *g, int allow_slide) |