summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/clk/clk.c
diff options
context:
space:
mode:
authorVijayakumar <vsubbu@nvidia.com>2016-09-16 09:26:22 -0400
committerDeepak Nibade <dnibade@nvidia.com>2016-12-27 04:56:50 -0500
commitc7fbd76e7101b7dedc8c0f04437288d1d6b78adc (patch)
tree6d1ab41af52a481ddeb148307a69113582569edd /drivers/gpu/nvgpu/clk/clk.c
parent3c351f5bb2d04c1f70c72f3f2fd758bbb340877c (diff)
gpu: nvgpu: create function to program coreclk
JIRA DNVGPU-123 now a function can be called with GPC2CLK value It will take care calculating slave clock values and calling VF inject to program clock Made programming of boot clock code to use this newly created function. Change-Id: I74de7e9d98e379e94175ed2d9745ce3ab6c70691 Signed-off-by: Vijayakumar <vsubbu@nvidia.com> Reviewed-on: http://git-master/r/1221976 GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-on: http://git-master/r/1235056
Diffstat (limited to 'drivers/gpu/nvgpu/clk/clk.c')
-rw-r--r--drivers/gpu/nvgpu/clk/clk.c229
1 files changed, 217 insertions, 12 deletions
diff --git a/drivers/gpu/nvgpu/clk/clk.c b/drivers/gpu/nvgpu/clk/clk.c
index 7ee4f283..918cd43c 100644
--- a/drivers/gpu/nvgpu/clk/clk.c
+++ b/drivers/gpu/nvgpu/clk/clk.c
@@ -104,7 +104,7 @@ done:
104 return status; 104 return status;
105} 105}
106 106
107u32 clk_pmu_vf_inject(struct gk20a *g) 107static u32 clk_pmu_vf_inject(struct gk20a *g, struct set_fll_clk *setfllclk)
108{ 108{
109 struct pmu_cmd cmd; 109 struct pmu_cmd cmd;
110 struct pmu_msg msg; 110 struct pmu_msg msg;
@@ -115,35 +115,48 @@ u32 clk_pmu_vf_inject(struct gk20a *g)
115 struct clkrpc_pmucmdhandler_params handler = {0}; 115 struct clkrpc_pmucmdhandler_params handler = {0};
116 struct nv_pmu_clk_vf_change_inject *vfchange; 116 struct nv_pmu_clk_vf_change_inject *vfchange;
117 117
118 if ((setfllclk->gpc2clkmhz == 0) || (setfllclk->xbar2clkmhz == 0) ||
119 (setfllclk->sys2clkmhz == 0) || (setfllclk->voltuv == 0))
120 return -EINVAL;
121
122 if ((setfllclk->target_regime_id_gpc > CTRL_CLK_FLL_REGIME_ID_FR) ||
123 (setfllclk->target_regime_id_sys > CTRL_CLK_FLL_REGIME_ID_FR) ||
124 (setfllclk->target_regime_id_xbar > CTRL_CLK_FLL_REGIME_ID_FR))
125 return -EINVAL;
126
118 rpccall.function = NV_PMU_CLK_RPC_ID_CLK_VF_CHANGE_INJECT; 127 rpccall.function = NV_PMU_CLK_RPC_ID_CLK_VF_CHANGE_INJECT;
119 vfchange = &rpccall.params.clk_vf_change_inject; 128 vfchange = &rpccall.params.clk_vf_change_inject;
120 vfchange->flags = 0; 129 vfchange->flags = 0;
121 vfchange->clk_list.num_domains = 3; 130 vfchange->clk_list.num_domains = 3;
122 vfchange->clk_list.clk_domains[0].clk_domain = CTRL_CLK_DOMAIN_GPC2CLK; 131 vfchange->clk_list.clk_domains[0].clk_domain = CTRL_CLK_DOMAIN_GPC2CLK;
123 vfchange->clk_list.clk_domains[0].clk_freq_khz = 2581 * 1000; 132 vfchange->clk_list.clk_domains[0].clk_freq_khz =
133 setfllclk->gpc2clkmhz * 1000;
124 vfchange->clk_list.clk_domains[0].clk_flags = 0; 134 vfchange->clk_list.clk_domains[0].clk_flags = 0;
125 vfchange->clk_list.clk_domains[0].current_regime_id = 135 vfchange->clk_list.clk_domains[0].current_regime_id =
126 CTRL_CLK_FLL_REGIME_ID_FFR; 136 setfllclk->current_regime_id_gpc;
127 vfchange->clk_list.clk_domains[0].target_regime_id = 137 vfchange->clk_list.clk_domains[0].target_regime_id =
128 CTRL_CLK_FLL_REGIME_ID_FR; 138 setfllclk->target_regime_id_gpc;
129 vfchange->clk_list.clk_domains[1].clk_domain = CTRL_CLK_DOMAIN_XBAR2CLK; 139 vfchange->clk_list.clk_domains[1].clk_domain = CTRL_CLK_DOMAIN_XBAR2CLK;
130 vfchange->clk_list.clk_domains[1].clk_freq_khz = 2505 * 1000; 140 vfchange->clk_list.clk_domains[1].clk_freq_khz =
141 setfllclk->xbar2clkmhz * 1000;
131 vfchange->clk_list.clk_domains[1].clk_flags = 0; 142 vfchange->clk_list.clk_domains[1].clk_flags = 0;
132 vfchange->clk_list.clk_domains[1].current_regime_id = 143 vfchange->clk_list.clk_domains[1].current_regime_id =
133 CTRL_CLK_FLL_REGIME_ID_FFR; 144 setfllclk->current_regime_id_xbar;
134 vfchange->clk_list.clk_domains[1].target_regime_id = 145 vfchange->clk_list.clk_domains[1].target_regime_id =
135 CTRL_CLK_FLL_REGIME_ID_FR; 146 setfllclk->target_regime_id_xbar;
136 vfchange->clk_list.clk_domains[2].clk_domain = CTRL_CLK_DOMAIN_SYS2CLK; 147 vfchange->clk_list.clk_domains[2].clk_domain = CTRL_CLK_DOMAIN_SYS2CLK;
137 vfchange->clk_list.clk_domains[2].clk_freq_khz = 2328 * 1000; 148 vfchange->clk_list.clk_domains[2].clk_freq_khz =
149 setfllclk->sys2clkmhz * 1000;
138 vfchange->clk_list.clk_domains[2].clk_flags = 0; 150 vfchange->clk_list.clk_domains[2].clk_flags = 0;
139 vfchange->clk_list.clk_domains[2].current_regime_id = 151 vfchange->clk_list.clk_domains[2].current_regime_id =
140 CTRL_CLK_FLL_REGIME_ID_FFR; 152 setfllclk->current_regime_id_sys;
141 vfchange->clk_list.clk_domains[2].target_regime_id = 153 vfchange->clk_list.clk_domains[2].target_regime_id =
142 CTRL_CLK_FLL_REGIME_ID_FR; 154 setfllclk->target_regime_id_sys;
143 vfchange->volt_list.num_rails = 1; 155 vfchange->volt_list.num_rails = 1;
144 vfchange->volt_list.rails[0].volt_domain = CTRL_VOLT_DOMAIN_LOGIC; 156 vfchange->volt_list.rails[0].volt_domain = CTRL_VOLT_DOMAIN_LOGIC;
145 vfchange->volt_list.rails[0].voltage_uv = 825000; 157 vfchange->volt_list.rails[0].voltage_uv = setfllclk->voltuv;
146 vfchange->volt_list.rails[0].voltage_min_noise_unaware_uv = 825000; 158 vfchange->volt_list.rails[0].voltage_min_noise_unaware_uv =
159 setfllclk->voltuv;
147 160
148 cmd.hdr.unit_id = PMU_UNIT_CLK; 161 cmd.hdr.unit_id = PMU_UNIT_CLK;
149 cmd.hdr.size = (u32)sizeof(struct nv_pmu_clk_cmd) + 162 cmd.hdr.size = (u32)sizeof(struct nv_pmu_clk_cmd) +
@@ -189,6 +202,198 @@ done:
189 return status; 202 return status;
190} 203}
191 204
205static u32 find_regime_id(struct gk20a *g, u32 domain, u16 clkmhz)
206{
207 struct fll_device *pflldev;
208 u8 j;
209 struct clk_pmupstate *pclk = &g->clk_pmu;
210
211 BOARDOBJGRP_FOR_EACH(&(pclk->avfs_fllobjs.super.super),
212 struct fll_device *, pflldev, j) {
213 if (pflldev->clk_domain == domain) {
214 if (pflldev->regime_desc.fixed_freq_regime_limit_mhz >=
215 clkmhz)
216 return CTRL_CLK_FLL_REGIME_ID_FR;
217 else
218 return CTRL_CLK_FLL_REGIME_ID_FFR;
219 }
220 }
221 return CTRL_CLK_FLL_REGIME_ID_INVALID;
222}
223
224static int set_regime_id(struct gk20a *g, u32 domain, u32 regimeid)
225{
226 struct fll_device *pflldev;
227 u8 j;
228 struct clk_pmupstate *pclk = &g->clk_pmu;
229
230 BOARDOBJGRP_FOR_EACH(&(pclk->avfs_fllobjs.super.super),
231 struct fll_device *, pflldev, j) {
232 if (pflldev->clk_domain == domain) {
233 pflldev->regime_desc.regime_id = regimeid;
234 return 0;
235 }
236 }
237 return -EINVAL;
238}
239
240static int get_regime_id(struct gk20a *g, u32 domain, u32 *regimeid)
241{
242 struct fll_device *pflldev;
243 u8 j;
244 struct clk_pmupstate *pclk = &g->clk_pmu;
245
246 BOARDOBJGRP_FOR_EACH(&(pclk->avfs_fllobjs.super.super),
247 struct fll_device *, pflldev, j) {
248 if (pflldev->clk_domain == domain) {
249 *regimeid = pflldev->regime_desc.regime_id;
250 return 0;
251 }
252 }
253 return -EINVAL;
254}
255
256int clk_program_fllclks(struct gk20a *g, struct change_fll_clk *fllclk)
257{
258 int status = -EINVAL;
259 struct clk_domain *pdomain;
260 u8 i;
261 struct clk_pmupstate *pclk = &g->clk_pmu;
262 u16 clkmhz = 0;
263 struct clk_domain_3x_master *p3xmaster;
264 struct clk_domain_3x_slave *p3xslave;
265 unsigned long slaveidxmask;
266 struct set_fll_clk setfllclk;
267 bool foundxbar2clk = false;
268 bool foundsys2clk = false;
269
270 memset(&setfllclk, 0, sizeof(setfllclk));
271 if (fllclk->api_clk_domain != CTRL_CLK_DOMAIN_GPC2CLK)
272 return -EINVAL;
273 if (fllclk->voltuv == 0)
274 return -EINVAL;
275 if (fllclk->clkmhz == 0)
276 return -EINVAL;
277
278 mutex_lock(&pclk->changeclkmutex);
279
280 setfllclk.voltuv = fllclk->voltuv;
281 setfllclk.gpc2clkmhz = fllclk->clkmhz;
282
283 BOARDOBJGRP_FOR_EACH(&(pclk->clk_domainobjs.super.super),
284 struct clk_domain *, pdomain, i) {
285
286 if (pdomain->api_domain == fllclk->api_clk_domain) {
287
288 if (!pdomain->super.implements(g, &pdomain->super,
289 CTRL_CLK_CLK_DOMAIN_TYPE_3X_MASTER)) {
290 status = -EINVAL;
291 goto done;
292 }
293 p3xmaster = (struct clk_domain_3x_master *)pdomain;
294 slaveidxmask = p3xmaster->slave_idxs_mask;
295 for_each_set_bit(i, &slaveidxmask, 32) {
296 p3xslave = (struct clk_domain_3x_slave *)
297 CLK_CLK_DOMAIN_GET(pclk, i);
298 if ((p3xslave->super.super.super.api_domain !=
299 CTRL_CLK_DOMAIN_XBAR2CLK) &&
300 (p3xslave->super.super.super.api_domain !=
301 CTRL_CLK_DOMAIN_SYS2CLK))
302 continue;
303 clkmhz = 0;
304 status = p3xslave->clkdomainclkgetslaveclk(g,
305 pclk,
306 (struct clk_domain *)p3xslave,
307 &clkmhz,
308 fllclk->clkmhz);
309 if (status) {
310 status = -EINVAL;
311 goto done;
312 }
313 if (p3xslave->super.super.super.api_domain ==
314 CTRL_CLK_DOMAIN_XBAR2CLK) {
315 setfllclk.xbar2clkmhz = clkmhz;
316 foundxbar2clk = true;
317 }
318 if (p3xslave->super.super.super.api_domain ==
319 CTRL_CLK_DOMAIN_SYS2CLK) {
320 setfllclk.sys2clkmhz = clkmhz;
321 foundsys2clk = true;
322 }
323 }
324 }
325 }
326 if (!(foundxbar2clk && foundsys2clk)) {
327 status = -EINVAL;
328 goto done;
329 }
330 /*set regime ids */
331 status = get_regime_id(g, CTRL_CLK_DOMAIN_GPC2CLK,
332 &setfllclk.current_regime_id_gpc);
333 if (status)
334 goto done;
335
336 setfllclk.target_regime_id_gpc = find_regime_id(g,
337 CTRL_CLK_DOMAIN_GPC2CLK, setfllclk.gpc2clkmhz);
338
339 status = get_regime_id(g, CTRL_CLK_DOMAIN_SYS2CLK,
340 &setfllclk.current_regime_id_sys);
341 if (status)
342 goto done;
343
344 setfllclk.target_regime_id_sys = find_regime_id(g,
345 CTRL_CLK_DOMAIN_SYS2CLK, setfllclk.sys2clkmhz);
346
347 status = get_regime_id(g, CTRL_CLK_DOMAIN_XBAR2CLK,
348 &setfllclk.current_regime_id_xbar);
349 if (status)
350 goto done;
351
352 setfllclk.target_regime_id_xbar = find_regime_id(g,
353 CTRL_CLK_DOMAIN_XBAR2CLK, setfllclk.xbar2clkmhz);
354
355 status = clk_pmu_vf_inject(g, &setfllclk);
356
357 if (status)
358 gk20a_err(dev_from_gk20a(g),
359 "vf inject to change clk failed");
360
361 /* save regime ids */
362 status = set_regime_id(g, CTRL_CLK_DOMAIN_XBAR2CLK,
363 setfllclk.target_regime_id_xbar);
364 if (status)
365 goto done;
366
367 status = set_regime_id(g, CTRL_CLK_DOMAIN_GPC2CLK,
368 setfllclk.target_regime_id_gpc);
369 if (status)
370 goto done;
371
372 status = set_regime_id(g, CTRL_CLK_DOMAIN_SYS2CLK,
373 setfllclk.target_regime_id_sys);
374 if (status)
375 goto done;
376done:
377 mutex_unlock(&pclk->changeclkmutex);
378 return status;
379}
380
381int clk_set_boot_fll_clk(struct gk20a *g)
382{
383 int status;
384 struct change_fll_clk bootfllclk;
385
386 mutex_init(&g->clk_pmu.changeclkmutex);
387
388 bootfllclk.api_clk_domain = CTRL_CLK_DOMAIN_GPC2CLK;
389 bootfllclk.clkmhz = 2581;
390 bootfllclk.voltuv = 825000;
391 status = clk_program_fllclks(g, &bootfllclk);
392 if (status)
393 gk20a_err(dev_from_gk20a(g), "attemp to set boot clk failed");
394 return status;
395}
396
192u32 clk_domain_print_vf_table(struct gk20a *g, u32 clkapidomain) 397u32 clk_domain_print_vf_table(struct gk20a *g, u32 clkapidomain)
193{ 398{
194 u32 status = -EINVAL; 399 u32 status = -EINVAL;