diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk_arb.c | 67 |
1 files changed, 62 insertions, 5 deletions
diff --git a/drivers/gpu/nvgpu/clk/clk_arb.c b/drivers/gpu/nvgpu/clk/clk_arb.c index ee75ce64..762c2466 100644 --- a/drivers/gpu/nvgpu/clk/clk_arb.c +++ b/drivers/gpu/nvgpu/clk/clk_arb.c | |||
@@ -44,9 +44,17 @@ static void nvgpu_clk_arb_free_session(struct kref *refcount); | |||
44 | static int nvgpu_clk_arb_change_vf_point(struct gk20a *g, u16 gpc2clk_target, | 44 | static int nvgpu_clk_arb_change_vf_point(struct gk20a *g, u16 gpc2clk_target, |
45 | u16 sys2clk_target, u16 xbar2clk_target, u16 mclk_target, u32 voltuv, | 45 | u16 sys2clk_target, u16 xbar2clk_target, u16 mclk_target, u32 voltuv, |
46 | u32 voltuv_sram); | 46 | u32 voltuv_sram); |
47 | static int nvgpu_clk_arb_change_vf_point_prefix(struct gk20a *g, | ||
48 | u16 gpc2clk_target, u16 sys2clk_target, u16 xbar2clk_target, | ||
49 | u16 mclk_target, u32 voltuv, u32 voltuv_sram, u32 nuvmin, | ||
50 | u32 nuvmin_sram); | ||
51 | static int nvgpu_clk_arb_change_vf_point_postfix(struct gk20a *g, | ||
52 | u16 gpc2clk_target, u16 sys2clk_target, u16 xbar2clk_target, | ||
53 | u16 mclk_target, u32 voltuv, u32 voltuv_sram, u32 nuvmin, | ||
54 | u32 nuvmin_sram); | ||
47 | static u8 nvgpu_clk_arb_find_vf_point(struct nvgpu_clk_arb *arb, | 55 | static u8 nvgpu_clk_arb_find_vf_point(struct nvgpu_clk_arb *arb, |
48 | u16 *gpc2clk_target, u16 *sys2clk_target, u16 *xbar2clk_target, | 56 | u16 *gpc2clk, u16 *sys2clk, u16 *xbar2clk, u16 *mclk, |
49 | u16 *mclk_target, u32 *voltuv, u32 *voltuv_sram); | 57 | u32 *voltuv, u32 *voltuv_sram, u32 *nuvmin, u32 *nuvmin_sram); |
50 | 58 | ||
51 | #define VF_POINT_INVALID_PSTATE ~0U | 59 | #define VF_POINT_INVALID_PSTATE ~0U |
52 | #define VF_POINT_SET_PSTATE_SUPPORTED(a, b) ((a)->pstates |= (1UL << (b))) | 60 | #define VF_POINT_SET_PSTATE_SUPPORTED(a, b) ((a)->pstates |= (1UL << (b))) |
@@ -797,6 +805,7 @@ static void nvgpu_clk_arb_run_arbiter_cb(struct work_struct *work) | |||
797 | u32 pstate = VF_POINT_INVALID_PSTATE; | 805 | u32 pstate = VF_POINT_INVALID_PSTATE; |
798 | u32 voltuv, voltuv_sram; | 806 | u32 voltuv, voltuv_sram; |
799 | bool mclk_set, gpc2clk_set; | 807 | bool mclk_set, gpc2clk_set; |
808 | u32 nuvmin, nuvmin_sram; | ||
800 | 809 | ||
801 | int status = 0; | 810 | int status = 0; |
802 | 811 | ||
@@ -879,7 +888,7 @@ static void nvgpu_clk_arb_run_arbiter_cb(struct work_struct *work) | |||
879 | /* Query the table for the closest vf point to program */ | 888 | /* Query the table for the closest vf point to program */ |
880 | pstate = nvgpu_clk_arb_find_vf_point(arb, &gpc2clk_target, | 889 | pstate = nvgpu_clk_arb_find_vf_point(arb, &gpc2clk_target, |
881 | &sys2clk_target, &xbar2clk_target, &mclk_target, &voltuv, | 890 | &sys2clk_target, &xbar2clk_target, &mclk_target, &voltuv, |
882 | &voltuv_sram); | 891 | &voltuv_sram, &nuvmin, &nuvmin_sram); |
883 | 892 | ||
884 | if (pstate == VF_POINT_INVALID_PSTATE) { | 893 | if (pstate == VF_POINT_INVALID_PSTATE) { |
885 | arb->status = -EINVAL; | 894 | arb->status = -EINVAL; |
@@ -897,6 +906,17 @@ static void nvgpu_clk_arb_run_arbiter_cb(struct work_struct *work) | |||
897 | /* Program clocks */ | 906 | /* Program clocks */ |
898 | /* A change in both mclk of gpc2clk may require a change in voltage */ | 907 | /* A change in both mclk of gpc2clk may require a change in voltage */ |
899 | 908 | ||
909 | status = nvgpu_clk_arb_change_vf_point_prefix(g, gpc2clk_target, | ||
910 | sys2clk_target, xbar2clk_target, mclk_target, voltuv, | ||
911 | voltuv_sram, nuvmin, nuvmin_sram); | ||
912 | |||
913 | if (status < 0) { | ||
914 | arb->status = status; | ||
915 | /* make status visible */ | ||
916 | smp_mb(); | ||
917 | goto exit_arb; | ||
918 | } | ||
919 | |||
900 | status = nvgpu_clk_arb_change_vf_point(g, gpc2clk_target, | 920 | status = nvgpu_clk_arb_change_vf_point(g, gpc2clk_target, |
901 | sys2clk_target, xbar2clk_target, mclk_target, voltuv, | 921 | sys2clk_target, xbar2clk_target, mclk_target, voltuv, |
902 | voltuv_sram); | 922 | voltuv_sram); |
@@ -905,9 +925,20 @@ static void nvgpu_clk_arb_run_arbiter_cb(struct work_struct *work) | |||
905 | arb->status = status; | 925 | arb->status = status; |
906 | /* make status visible */ | 926 | /* make status visible */ |
907 | smp_mb(); | 927 | smp_mb(); |
928 | goto exit_arb; | ||
929 | } | ||
930 | |||
931 | status = nvgpu_clk_arb_change_vf_point_postfix(g, gpc2clk_target, | ||
932 | sys2clk_target, xbar2clk_target, mclk_target, voltuv, | ||
933 | voltuv_sram, nuvmin, nuvmin_sram); | ||
908 | 934 | ||
935 | if (status < 0) { | ||
936 | arb->status = status; | ||
937 | /* make status visible */ | ||
938 | smp_mb(); | ||
909 | goto exit_arb; | 939 | goto exit_arb; |
910 | } | 940 | } |
941 | |||
911 | actual = ACCESS_ONCE(arb->actual) == &arb->actual_pool[0] ? | 942 | actual = ACCESS_ONCE(arb->actual) == &arb->actual_pool[0] ? |
912 | &arb->actual_pool[1] : &arb->actual_pool[0]; | 943 | &arb->actual_pool[1] : &arb->actual_pool[0]; |
913 | 944 | ||
@@ -1189,7 +1220,7 @@ int nvgpu_clk_arb_get_arbiter_clk_f_points(struct gk20a *g, | |||
1189 | 1220 | ||
1190 | static u8 nvgpu_clk_arb_find_vf_point(struct nvgpu_clk_arb *arb, | 1221 | static u8 nvgpu_clk_arb_find_vf_point(struct nvgpu_clk_arb *arb, |
1191 | u16 *gpc2clk, u16 *sys2clk, u16 *xbar2clk, u16 *mclk, | 1222 | u16 *gpc2clk, u16 *sys2clk, u16 *xbar2clk, u16 *mclk, |
1192 | u32 *voltuv, u32 *voltuv_sram) | 1223 | u32 *voltuv, u32 *voltuv_sram, u32 *nuvmin, u32 *nuvmin_sram) |
1193 | { | 1224 | { |
1194 | u16 gpc2clk_target, mclk_target; | 1225 | u16 gpc2clk_target, mclk_target; |
1195 | u32 gpc2clk_voltuv, gpc2clk_voltuv_sram; | 1226 | u32 gpc2clk_voltuv, gpc2clk_voltuv_sram; |
@@ -1301,12 +1332,38 @@ find_exit: | |||
1301 | *voltuv = gpc2clk_voltuv > mclk_voltuv ? gpc2clk_voltuv : mclk_voltuv; | 1332 | *voltuv = gpc2clk_voltuv > mclk_voltuv ? gpc2clk_voltuv : mclk_voltuv; |
1302 | *voltuv_sram = gpc2clk_voltuv_sram > mclk_voltuv_sram ? | 1333 | *voltuv_sram = gpc2clk_voltuv_sram > mclk_voltuv_sram ? |
1303 | gpc2clk_voltuv_sram : mclk_voltuv_sram; | 1334 | gpc2clk_voltuv_sram : mclk_voltuv_sram; |
1304 | 1335 | /* noise unaware vmin */ | |
1336 | *nuvmin = mclk_voltuv; | ||
1337 | *nuvmin_sram = mclk_voltuv_sram; | ||
1305 | *gpc2clk = gpc2clk_target; | 1338 | *gpc2clk = gpc2clk_target; |
1306 | *mclk = mclk_target; | 1339 | *mclk = mclk_target; |
1307 | return pstate; | 1340 | return pstate; |
1308 | } | 1341 | } |
1309 | 1342 | ||
1343 | static int nvgpu_clk_arb_change_vf_point_prefix(struct gk20a *g, | ||
1344 | u16 gpc2clk_target, u16 sys2clk_target, u16 xbar2clk_target, | ||
1345 | u16 mclk_target, u32 voltuv, u32 voltuv_sram, u32 nuvmin, | ||
1346 | u32 nuvmin_sram) | ||
1347 | { | ||
1348 | |||
1349 | int status; | ||
1350 | |||
1351 | status = clk_pmu_freq_controller_load(g, false); | ||
1352 | if (status < 0) | ||
1353 | return status; | ||
1354 | |||
1355 | status = volt_set_noiseaware_vmin(g, nuvmin, nuvmin_sram); | ||
1356 | return status; | ||
1357 | } | ||
1358 | |||
1359 | static int nvgpu_clk_arb_change_vf_point_postfix(struct gk20a *g, | ||
1360 | u16 gpc2clk_target, u16 sys2clk_target, u16 xbar2clk_target, | ||
1361 | u16 mclk_target, u32 voltuv, u32 voltuv_sram, u32 nuvmin, | ||
1362 | u32 nuvmin_sram) | ||
1363 | { | ||
1364 | return clk_pmu_freq_controller_load(g, true); | ||
1365 | } | ||
1366 | |||
1310 | static int nvgpu_clk_arb_change_vf_point(struct gk20a *g, u16 gpc2clk_target, | 1367 | static int nvgpu_clk_arb_change_vf_point(struct gk20a *g, u16 gpc2clk_target, |
1311 | u16 sys2clk_target, u16 xbar2clk_target, u16 mclk_target, u32 voltuv, | 1368 | u16 sys2clk_target, u16 xbar2clk_target, u16 mclk_target, u32 voltuv, |
1312 | u32 voltuv_sram) | 1369 | u32 voltuv_sram) |