summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/nvgpu/Makefile.nvgpu-t18x1
-rw-r--r--drivers/gpu/nvgpu/clk/clk.c72
-rw-r--r--drivers/gpu/nvgpu/clk/clk.h4
-rw-r--r--drivers/gpu/nvgpu/clk/clk_freq_controller.c454
-rw-r--r--drivers/gpu/nvgpu/clk/clk_freq_controller.h74
-rw-r--r--drivers/gpu/nvgpu/include/bios.h83
-rw-r--r--drivers/gpu/nvgpu/pstate/pstate.c9
7 files changed, 696 insertions, 1 deletions
diff --git a/drivers/gpu/nvgpu/Makefile.nvgpu-t18x b/drivers/gpu/nvgpu/Makefile.nvgpu-t18x
index a096a438..9e08e2c6 100644
--- a/drivers/gpu/nvgpu/Makefile.nvgpu-t18x
+++ b/drivers/gpu/nvgpu/Makefile.nvgpu-t18x
@@ -39,6 +39,7 @@ nvgpu-y += \
39 $(nvgpu-t18x)/clk/clk_prog.o \ 39 $(nvgpu-t18x)/clk/clk_prog.o \
40 $(nvgpu-t18x)/clk/clk_vf_point.o \ 40 $(nvgpu-t18x)/clk/clk_vf_point.o \
41 $(nvgpu-t18x)/clk/clk_arb.o \ 41 $(nvgpu-t18x)/clk/clk_arb.o \
42 $(nvgpu-t18x)/clk/clk_freq_controller.o \
42 $(nvgpu-t18x)/perf/vfe_var.o \ 43 $(nvgpu-t18x)/perf/vfe_var.o \
43 $(nvgpu-t18x)/perf/vfe_equ.o \ 44 $(nvgpu-t18x)/perf/vfe_equ.o \
44 $(nvgpu-t18x)/perf/perf.o \ 45 $(nvgpu-t18x)/perf/perf.o \
diff --git a/drivers/gpu/nvgpu/clk/clk.c b/drivers/gpu/nvgpu/clk/clk.c
index 07c80e22..dffbefec 100644
--- a/drivers/gpu/nvgpu/clk/clk.c
+++ b/drivers/gpu/nvgpu/clk/clk.c
@@ -47,6 +47,78 @@ static void clkrpc_pmucmdhandler(struct gk20a *g, struct pmu_msg *msg,
47 phandlerparams->success = 1; 47 phandlerparams->success = 1;
48} 48}
49 49
50int clk_pmu_freq_controller_load(struct gk20a *g, bool bload)
51{
52 struct pmu_cmd cmd;
53 struct pmu_msg msg;
54 struct pmu_payload payload = { {0} };
55 u32 status;
56 u32 seqdesc;
57 struct nv_pmu_clk_rpc rpccall = {0};
58 struct clkrpc_pmucmdhandler_params handler = {0};
59 struct nv_pmu_clk_load *clkload;
60 struct clk_freq_controllers *pclk_freq_controllers;
61 struct ctrl_boardobjgrp_mask_e32 *load_mask;
62
63 pclk_freq_controllers = &g->clk_pmu.clk_freq_controllers;
64 rpccall.function = NV_PMU_CLK_RPC_ID_LOAD;
65 clkload = &rpccall.params.clk_load;
66 clkload->feature = NV_NV_PMU_CLK_LOAD_FEATURE_FREQ_CONTROLLER;
67 clkload->action_mask = bload ?
68 NV_NV_PMU_CLK_LOAD_ACTION_MASK_FREQ_CONTROLLER_CALLBACK_YES :
69 NV_NV_PMU_CLK_LOAD_ACTION_MASK_FREQ_CONTROLLER_CALLBACK_NO;
70
71 load_mask = &rpccall.params.clk_load.payload.freq_controllers.load_mask;
72
73 status = boardobjgrpmask_export(
74 &pclk_freq_controllers->freq_ctrl_load_mask.super,
75 pclk_freq_controllers->freq_ctrl_load_mask.super.bitcount,
76 &load_mask->super);
77
78 cmd.hdr.unit_id = PMU_UNIT_CLK;
79 cmd.hdr.size = (u32)sizeof(struct nv_pmu_clk_cmd) +
80 (u32)sizeof(struct pmu_hdr);
81
82 cmd.cmd.clk.cmd_type = NV_PMU_CLK_CMD_ID_RPC;
83 msg.hdr.size = sizeof(struct pmu_msg);
84
85 payload.in.buf = (u8 *)&rpccall;
86 payload.in.size = (u32)sizeof(struct nv_pmu_clk_rpc);
87 payload.in.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED;
88 payload.in.offset = NV_PMU_CLK_CMD_RPC_ALLOC_OFFSET;
89
90 payload.out.buf = (u8 *)&rpccall;
91 payload.out.size = (u32)sizeof(struct nv_pmu_clk_rpc);
92 payload.out.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED;
93 payload.out.offset = NV_PMU_CLK_MSG_RPC_ALLOC_OFFSET;
94
95 handler.prpccall = &rpccall;
96 handler.success = 0;
97 status = gk20a_pmu_cmd_post(g, &cmd, NULL, &payload,
98 PMU_COMMAND_QUEUE_LPQ,
99 clkrpc_pmucmdhandler, (void *)&handler,
100 &seqdesc, ~0);
101
102 if (status) {
103 gk20a_err(dev_from_gk20a(g),
104 "unable to post clk RPC cmd %x",
105 cmd.cmd.clk.cmd_type);
106 goto done;
107 }
108
109 pmu_wait_message_cond(&g->pmu,
110 gk20a_get_gr_idle_timeout(g),
111 &handler.success, 1);
112
113 if (handler.success == 0) {
114 gk20a_err(dev_from_gk20a(g), "rpc call to load freq cntlr cal failed");
115 status = -EINVAL;
116 }
117
118done:
119 return status;
120}
121
50u32 clk_pmu_vin_load(struct gk20a *g) 122u32 clk_pmu_vin_load(struct gk20a *g)
51{ 123{
52 struct pmu_cmd cmd; 124 struct pmu_cmd cmd;
diff --git a/drivers/gpu/nvgpu/clk/clk.h b/drivers/gpu/nvgpu/clk/clk.h
index 42cb9f7d..b173a09e 100644
--- a/drivers/gpu/nvgpu/clk/clk.h
+++ b/drivers/gpu/nvgpu/clk/clk.h
@@ -21,6 +21,7 @@
21#include "clk_prog.h" 21#include "clk_prog.h"
22#include "clk_vf_point.h" 22#include "clk_vf_point.h"
23#include "clk_mclk.h" 23#include "clk_mclk.h"
24#include "clk_freq_controller.h"
24#include "gk20a/gk20a.h" 25#include "gk20a/gk20a.h"
25 26
26#define NV_PERF_DOMAIN_4X_CLOCK_DOMAIN_SKIP 0x10 27#define NV_PERF_DOMAIN_4X_CLOCK_DOMAIN_SKIP 0x10
@@ -35,6 +36,7 @@ struct clk_pmupstate {
35 struct clk_progs clk_progobjs; 36 struct clk_progs clk_progobjs;
36 struct clk_vf_points clk_vf_pointobjs; 37 struct clk_vf_points clk_vf_pointobjs;
37 struct clk_mclk_state clk_mclk; 38 struct clk_mclk_state clk_mclk;
39 struct clk_freq_controllers clk_freq_controllers;
38}; 40};
39 41
40struct clockentry { 42struct clockentry {
@@ -114,5 +116,5 @@ u32 clk_domain_get_f_points(
114); 116);
115int clk_get_fll_clks(struct gk20a *g, struct set_fll_clk *fllclk); 117int clk_get_fll_clks(struct gk20a *g, struct set_fll_clk *fllclk);
116int clk_set_fll_clks(struct gk20a *g, struct set_fll_clk *fllclk); 118int clk_set_fll_clks(struct gk20a *g, struct set_fll_clk *fllclk);
117 119int clk_pmu_freq_controller_load(struct gk20a *g, bool bload);
118#endif 120#endif
diff --git a/drivers/gpu/nvgpu/clk/clk_freq_controller.c b/drivers/gpu/nvgpu/clk/clk_freq_controller.c
new file mode 100644
index 00000000..17f79168
--- /dev/null
+++ b/drivers/gpu/nvgpu/clk/clk_freq_controller.c
@@ -0,0 +1,454 @@
1/*
2 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 */
13
14#include "gk20a/gk20a.h"
15#include "clk.h"
16#include "clk_fll.h"
17#include "clk_domain.h"
18#include "clk_freq_controller.h"
19#include "include/bios.h"
20#include "boardobj/boardobjgrp.h"
21#include "boardobj/boardobjgrp_e32.h"
22#include "pmuif/gpmuifboardobj.h"
23#include "pmuif/gpmuifclk.h"
24#include "gm206/bios_gm206.h"
25#include "ctrl/ctrlclk.h"
26#include "ctrl/ctrlvolt.h"
27#include "gk20a/pmu_gk20a.h"
28
29static u32 clk_freq_controller_pmudatainit_super(struct gk20a *g,
30 struct boardobj *board_obj_ptr,
31 struct nv_pmu_boardobj *ppmudata)
32{
33 struct nv_pmu_clk_clk_freq_controller_boardobj_set *pfreq_cntlr_set;
34 struct clk_freq_controller *pfreq_cntlr;
35 u32 status = 0;
36
37 status = boardobj_pmudatainit_super(g, board_obj_ptr, ppmudata);
38 if (status)
39 return status;
40
41 pfreq_cntlr_set =
42 (struct nv_pmu_clk_clk_freq_controller_boardobj_set *)ppmudata;
43 pfreq_cntlr = (struct clk_freq_controller *)board_obj_ptr;
44
45 pfreq_cntlr_set->controller_id = pfreq_cntlr->controller_id;
46 pfreq_cntlr_set->clk_domain = pfreq_cntlr->clk_domain;
47 pfreq_cntlr_set->parts_freq_mode = pfreq_cntlr->parts_freq_mode;
48 pfreq_cntlr_set->bdisable = pfreq_cntlr->bdisable;
49 pfreq_cntlr_set->freq_cap_noise_unaware_vmin_above =
50 pfreq_cntlr->freq_cap_noise_unaware_vmin_above;
51 pfreq_cntlr_set->freq_cap_noise_unaware_vmin_below =
52 pfreq_cntlr->freq_cap_noise_unaware_vmin_below;
53 pfreq_cntlr_set->freq_hyst_pos_mhz = pfreq_cntlr->freq_hyst_pos_mhz;
54 pfreq_cntlr_set->freq_hyst_neg_mhz = pfreq_cntlr->freq_hyst_neg_mhz;
55
56 return status;
57}
58
59static u32 clk_freq_controller_pmudatainit_pi(struct gk20a *g,
60 struct boardobj *board_obj_ptr,
61 struct nv_pmu_boardobj *ppmudata)
62{
63 struct nv_pmu_clk_clk_freq_controller_pi_boardobj_set
64 *pfreq_cntlr_pi_set;
65 struct clk_freq_controller_pi *pfreq_cntlr_pi;
66 u32 status = 0;
67
68 status = clk_freq_controller_pmudatainit_super(g,
69 board_obj_ptr, ppmudata);
70 if (status)
71 return -1;
72
73 pfreq_cntlr_pi_set =
74 (struct nv_pmu_clk_clk_freq_controller_pi_boardobj_set *)
75 ppmudata;
76 pfreq_cntlr_pi = (struct clk_freq_controller_pi *)board_obj_ptr;
77
78 pfreq_cntlr_pi_set->prop_gain = pfreq_cntlr_pi->prop_gain;
79 pfreq_cntlr_pi_set->integ_gain = pfreq_cntlr_pi->integ_gain;
80 pfreq_cntlr_pi_set->integ_decay = pfreq_cntlr_pi->integ_decay;
81 pfreq_cntlr_pi_set->volt_delta_min = pfreq_cntlr_pi->volt_delta_min;
82 pfreq_cntlr_pi_set->volt_delta_max = pfreq_cntlr_pi->volt_delta_max;
83 pfreq_cntlr_pi_set->slowdown_pct_min = pfreq_cntlr_pi->slowdown_pct_min;
84 pfreq_cntlr_pi_set->bpoison = pfreq_cntlr_pi->bpoison;
85
86 return status;
87}
88
89static u32 clk_freq_controller_construct_super(struct gk20a *g,
90 struct boardobj **ppboardobj,
91 u16 size, void *pargs)
92{
93 struct clk_freq_controller *pfreq_cntlr = NULL;
94 struct clk_freq_controller *pfreq_cntlr_tmp = NULL;
95 u32 status = 0;
96
97 status = boardobj_construct_super(g, ppboardobj, size, pargs);
98 if (status)
99 return -EINVAL;
100
101 pfreq_cntlr_tmp = (struct clk_freq_controller *)pargs;
102 pfreq_cntlr = (struct clk_freq_controller *)*ppboardobj;
103
104 pfreq_cntlr->super.pmudatainit = clk_freq_controller_pmudatainit_super;
105
106 pfreq_cntlr->controller_id = pfreq_cntlr_tmp->controller_id;
107 pfreq_cntlr->clk_domain = pfreq_cntlr_tmp->clk_domain;
108 pfreq_cntlr->parts_freq_mode = pfreq_cntlr_tmp->parts_freq_mode;
109 pfreq_cntlr->freq_cap_noise_unaware_vmin_above =
110 pfreq_cntlr_tmp->freq_cap_noise_unaware_vmin_above;
111 pfreq_cntlr->freq_cap_noise_unaware_vmin_below =
112 pfreq_cntlr_tmp->freq_cap_noise_unaware_vmin_below;
113 pfreq_cntlr->freq_hyst_pos_mhz = pfreq_cntlr_tmp->freq_hyst_pos_mhz;
114 pfreq_cntlr->freq_hyst_neg_mhz = pfreq_cntlr_tmp->freq_hyst_neg_mhz;
115
116 return status;
117}
118
119static u32 clk_freq_controller_construct_pi(struct gk20a *g,
120 struct boardobj **ppboardobj,
121 u16 size, void *pargs)
122{
123 struct clk_freq_controller_pi *pfreq_cntlr_pi = NULL;
124 struct clk_freq_controller_pi *pfreq_cntlr_pi_tmp = NULL;
125 u32 status = 0;
126
127 status = clk_freq_controller_construct_super(g, ppboardobj,
128 size, pargs);
129 if (status)
130 return -EINVAL;
131
132 pfreq_cntlr_pi = (struct clk_freq_controller_pi *)*ppboardobj;
133 pfreq_cntlr_pi_tmp = (struct clk_freq_controller_pi *)pargs;
134
135 pfreq_cntlr_pi->super.super.pmudatainit =
136 clk_freq_controller_pmudatainit_pi;
137
138 pfreq_cntlr_pi->prop_gain = pfreq_cntlr_pi_tmp->prop_gain;
139 pfreq_cntlr_pi->integ_gain = pfreq_cntlr_pi_tmp->integ_gain;
140 pfreq_cntlr_pi->integ_decay = pfreq_cntlr_pi_tmp->integ_decay;
141 pfreq_cntlr_pi->volt_delta_min = pfreq_cntlr_pi_tmp->volt_delta_min;
142 pfreq_cntlr_pi->volt_delta_max = pfreq_cntlr_pi_tmp->volt_delta_max;
143 pfreq_cntlr_pi->slowdown_pct_min = pfreq_cntlr_pi_tmp->slowdown_pct_min;
144 pfreq_cntlr_pi->bpoison = pfreq_cntlr_pi_tmp->bpoison;
145
146 return status;
147}
148
149struct clk_freq_controller *clk_clk_freq_controller_construct(struct gk20a *g,
150 void *pargs)
151{
152 struct boardobj *board_obj_ptr = NULL;
153 u32 status = 0;
154
155 if (BOARDOBJ_GET_TYPE(pargs) != CTRL_CLK_CLK_FREQ_CONTROLLER_TYPE_PI)
156 return NULL;
157
158 status = clk_freq_controller_construct_pi(g, &board_obj_ptr,
159 sizeof(struct clk_freq_controller_pi), pargs);
160 if (status)
161 return NULL;
162
163 return (struct clk_freq_controller *)board_obj_ptr;
164}
165
166
167static u32 clk_get_freq_controller_table(struct gk20a *g,
168 struct clk_freq_controllers *pclk_freq_controllers)
169{
170 u32 status = 0;
171 u8 *pfreq_controller_table_ptr = NULL;
172 struct vbios_fct_1x_header header = { 0 };
173 struct vbios_fct_1x_entry entry = { 0 };
174 u8 entry_idx;
175 u8 *entry_offset;
176 u32 freq_controller_id;
177 struct clk_freq_controller *pclk_freq_cntr = NULL;
178 struct clk_freq_controller *ptmp_freq_cntr = NULL;
179 struct clk_freq_controller_pi *ptmp_freq_cntr_pi = NULL;
180 struct clk_domain *pclk_domain;
181
182 struct freq_controller_data_type {
183 union {
184 struct boardobj board_obj;
185 struct clk_freq_controller freq_controller;
186 struct clk_freq_controller_pi freq_controller_pi;
187 };
188 } freq_controller_data;
189
190 if (g->ops.bios.get_perf_table_ptrs) {
191 pfreq_controller_table_ptr =
192 (u8 *)g->ops.bios.get_perf_table_ptrs(g,
193 g->bios.clock_token,
194 FREQUENCY_CONTROLLER_TABLE);
195 if (pfreq_controller_table_ptr == NULL) {
196 status = -EINVAL;
197 goto done;
198 }
199 } else {
200 status = -EINVAL;
201 goto done;
202 }
203
204 memcpy(&header, pfreq_controller_table_ptr,
205 sizeof(struct vbios_fct_1x_header));
206
207 pclk_freq_controllers->sampling_period_ms = header.sampling_period_ms;
208 pclk_freq_controllers->volt_policy_idx = 0;
209
210 /* Read in the entries. */
211 for (entry_idx = 0; entry_idx < header.entry_count; entry_idx++) {
212 entry_offset = (pfreq_controller_table_ptr +
213 header.header_size + (entry_idx * header.entry_size));
214
215 memset(&freq_controller_data, 0x0,
216 sizeof(struct freq_controller_data_type));
217 ptmp_freq_cntr = &freq_controller_data.freq_controller;
218 ptmp_freq_cntr_pi = &freq_controller_data.freq_controller_pi;
219
220 memcpy(&entry, entry_offset,
221 sizeof(struct vbios_fct_1x_entry));
222
223 if (!BIOS_GET_FIELD(entry.flags0,
224 NV_VBIOS_FCT_1X_ENTRY_FLAGS0_TYPE))
225 continue;
226
227 freq_controller_data.board_obj.type = (u8)BIOS_GET_FIELD(
228 entry.flags0, NV_VBIOS_FCT_1X_ENTRY_FLAGS0_TYPE);
229
230 ptmp_freq_cntr->controller_id =
231 (u8)BIOS_GET_FIELD(entry.param0,
232 NV_VBIOS_FCT_1X_ENTRY_PARAM0_ID);
233
234 freq_controller_id = ptmp_freq_cntr->controller_id;
235
236 pclk_domain = CLK_CLK_DOMAIN_GET((&g->clk_pmu),
237 (u32)entry.clk_domain_idx);
238 freq_controller_data.freq_controller.clk_domain =
239 pclk_domain->api_domain;
240
241 ptmp_freq_cntr->parts_freq_mode =
242 (u8)BIOS_GET_FIELD(entry.param0,
243 NV_VBIOS_FCT_1X_ENTRY_PARAM0_FREQ_MODE);
244
245 /* Populate PI specific data */
246 ptmp_freq_cntr_pi->slowdown_pct_min =
247 (u8)BIOS_GET_FIELD(entry.param1,
248 NV_VBIOS_FCT_1X_ENTRY_PARAM1_SLOWDOWN_PCT_MIN);
249
250 ptmp_freq_cntr_pi->bpoison =
251 BIOS_GET_FIELD(entry.param1,
252 NV_VBIOS_FCT_1X_ENTRY_PARAM1_POISON);
253
254 ptmp_freq_cntr_pi->prop_gain =
255 (s32)BIOS_GET_FIELD(entry.param2,
256 NV_VBIOS_FCT_1X_ENTRY_PARAM2_PROP_GAIN);
257
258 ptmp_freq_cntr_pi->integ_gain =
259 (s32)BIOS_GET_FIELD(entry.param3,
260 NV_VBIOS_FCT_1X_ENTRY_PARAM3_INTEG_GAIN);
261
262 ptmp_freq_cntr_pi->integ_decay =
263 (s32)BIOS_GET_FIELD(entry.param4,
264 NV_VBIOS_FCT_1X_ENTRY_PARAM4_INTEG_DECAY);
265
266 ptmp_freq_cntr_pi->volt_delta_min =
267 (s32)BIOS_GET_FIELD(entry.param5,
268 NV_VBIOS_FCT_1X_ENTRY_PARAM5_VOLT_DELTA_MIN);
269
270 ptmp_freq_cntr_pi->volt_delta_max =
271 (s32)BIOS_GET_FIELD(entry.param6,
272 NV_VBIOS_FCT_1X_ENTRY_PARAM6_VOLT_DELTA_MAX);
273
274 ptmp_freq_cntr->freq_cap_noise_unaware_vmin_above =
275 (s16)BIOS_GET_FIELD(entry.param7,
276 NV_VBIOS_FCT_1X_ENTRY_PARAM7_FREQ_CAP_VF);
277
278 ptmp_freq_cntr->freq_cap_noise_unaware_vmin_below =
279 (s16)BIOS_GET_FIELD(entry.param7,
280 NV_VBIOS_FCT_1X_ENTRY_PARAM7_FREQ_CAP_VMIN);
281
282 ptmp_freq_cntr->freq_hyst_pos_mhz =
283 (s16)BIOS_GET_FIELD(entry.param8,
284 NV_VBIOS_FCT_1X_ENTRY_PARAM8_FREQ_HYST_POS);
285 ptmp_freq_cntr->freq_hyst_neg_mhz =
286 (s16)BIOS_GET_FIELD(entry.param8,
287 NV_VBIOS_FCT_1X_ENTRY_PARAM8_FREQ_HYST_NEG);
288
289 if (ptmp_freq_cntr_pi->volt_delta_max <
290 ptmp_freq_cntr_pi->volt_delta_min)
291 goto done;
292
293 pclk_freq_cntr = clk_clk_freq_controller_construct(g,
294 (void *)&freq_controller_data);
295
296 if (pclk_freq_cntr == NULL) {
297 gk20a_err(dev_from_gk20a(g),
298 "unable to construct clock freq cntlr boardobj for %d",
299 entry_idx);
300 status = -EINVAL;
301 goto done;
302 }
303
304 status = boardobjgrp_objinsert(
305 &pclk_freq_controllers->super.super,
306 (struct boardobj *)pclk_freq_cntr, entry_idx);
307 if (status) {
308 gk20a_err(dev_from_gk20a(g),
309 "unable to insert clock freq cntlr boardobj for");
310 status = -EINVAL;
311 goto done;
312 }
313
314 }
315
316done:
317 return status;
318}
319
320u32 clk_freq_controller_pmu_setup(struct gk20a *g)
321{
322 u32 status;
323 struct boardobjgrp *pboardobjgrp = NULL;
324
325 gk20a_dbg_info("");
326
327 pboardobjgrp = &g->clk_pmu.clk_freq_controllers.super.super;
328
329 if (!pboardobjgrp->bconstructed)
330 return -EINVAL;
331
332 status = pboardobjgrp->pmuinithandle(g, pboardobjgrp);
333
334 gk20a_dbg_info("Done");
335 return status;
336}
337
338static u32 _clk_freq_controller_devgrp_pmudata_instget(struct gk20a *g,
339 struct nv_pmu_boardobjgrp *pmuboardobjgrp,
340 struct nv_pmu_boardobj **ppboardobjpmudata,
341 u8 idx)
342{
343 struct nv_pmu_clk_clk_freq_controller_boardobj_grp_set *pgrp_set =
344 (struct nv_pmu_clk_clk_freq_controller_boardobj_grp_set *)
345 pmuboardobjgrp;
346
347 gk20a_dbg_info("");
348
349 /*check whether pmuboardobjgrp has a valid boardobj in index*/
350 if (((u32)BIT(idx) &
351 pgrp_set->hdr.data.super.obj_mask.super.data[0]) == 0)
352 return -EINVAL;
353
354 *ppboardobjpmudata = (struct nv_pmu_boardobj *)
355 &pgrp_set->objects[idx].data.board_obj;
356 gk20a_dbg_info(" Done");
357 return 0;
358}
359
360static u32 _clk_freq_controllers_pmudatainit(struct gk20a *g,
361 struct boardobjgrp *pboardobjgrp,
362 struct nv_pmu_boardobjgrp_super *pboardobjgrppmu)
363{
364 struct nv_pmu_clk_clk_freq_controller_boardobjgrp_set_header *pset =
365 (struct nv_pmu_clk_clk_freq_controller_boardobjgrp_set_header *)
366 pboardobjgrppmu;
367 struct clk_freq_controllers *pcntrs =
368 (struct clk_freq_controllers *)pboardobjgrp;
369 u32 status = 0;
370
371 status = boardobjgrp_pmudatainit_e32(g, pboardobjgrp, pboardobjgrppmu);
372 if (status) {
373 gk20a_err(dev_from_gk20a(g),
374 "error updating pmu boardobjgrp for clk freq ctrs 0x%x",
375 status);
376 goto done;
377 }
378 pset->sampling_period_ms = pcntrs->sampling_period_ms;
379 pset->volt_policy_idx = pcntrs->volt_policy_idx;
380
381done:
382 return status;
383}
384
385u32 clk_freq_controller_sw_setup(struct gk20a *g)
386{
387 u32 status = 0;
388 struct boardobjgrp *pboardobjgrp = NULL;
389 struct clk_freq_controllers *pclk_freq_controllers;
390 struct avfsfllobjs *pfllobjs = &(g->clk_pmu.avfs_fllobjs);
391 struct fll_device *pfll;
392 struct clk_freq_controller *pclkfreqctrl;
393 u8 i;
394 u8 j;
395
396 gk20a_dbg_info("");
397
398 pclk_freq_controllers = &g->clk_pmu.clk_freq_controllers;
399 status = boardobjgrpconstruct_e32(&pclk_freq_controllers->super);
400 if (status) {
401 gk20a_err(dev_from_gk20a(g),
402 "error creating boardobjgrp for clk FCT, status - 0x%x",
403 status);
404 goto done;
405 }
406
407 pboardobjgrp = &g->clk_pmu.clk_freq_controllers.super.super;
408
409 pboardobjgrp->pmudatainit = _clk_freq_controllers_pmudatainit;
410 pboardobjgrp->pmudatainstget =
411 _clk_freq_controller_devgrp_pmudata_instget;
412 pboardobjgrp->pmustatusinstget = NULL;
413
414 /* Initialize mask to zero.*/
415 boardobjgrpmask_e32_init(&pclk_freq_controllers->freq_ctrl_load_mask,
416 NULL);
417
418 BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, CLK, CLK_FREQ_CONTROLLER);
419
420 status = BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(g, pboardobjgrp,
421 clk, CLK, clk_freq_controller, CLK_FREQ_CONTROLLER);
422 if (status) {
423 gk20a_err(dev_from_gk20a(g),
424 "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x",
425 status);
426 goto done;
427 }
428
429 status = clk_get_freq_controller_table(g, pclk_freq_controllers);
430 if (status) {
431 gk20a_err(dev_from_gk20a(g),
432 "error reading freq controller table - 0x%x",
433 status);
434 goto done;
435 }
436
437 BOARDOBJGRP_FOR_EACH(&(pclk_freq_controllers->super.super),
438 struct clk_freq_controller *, pclkfreqctrl, i) {
439 pfll = NULL;
440 j = 0;
441 BOARDOBJGRP_FOR_EACH(&(pfllobjs->super.super),
442 struct fll_device *, pfll, j) {
443 if (pclkfreqctrl->controller_id == pfll->id) {
444 pfll->freq_ctrl_idx = i;
445 break;
446 }
447 }
448 boardobjgrpmask_bitset(&pclk_freq_controllers->
449 freq_ctrl_load_mask.super, i);
450 }
451done:
452 gk20a_dbg_info(" done status %x", status);
453 return status;
454}
diff --git a/drivers/gpu/nvgpu/clk/clk_freq_controller.h b/drivers/gpu/nvgpu/clk/clk_freq_controller.h
new file mode 100644
index 00000000..957a4f08
--- /dev/null
+++ b/drivers/gpu/nvgpu/clk/clk_freq_controller.h
@@ -0,0 +1,74 @@
1/*
2* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
3*
4* This program is free software; you can redistribute it and/or modify it
5* under the terms and conditions of the GNU General Public License,
6* version 2, as published by the Free Software Foundation.
7*
8* This program is distributed in the hope it will be useful, but WITHOUT
9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11* more details.
12*/
13
14#ifndef _CLK_FREQ_CONTROLLER_H_
15#define _CLK_FREQ_CONTROLLER_H_
16
17#define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_SYS 0x00
18#define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_LTC 0x01
19#define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_XBAR 0x02
20#define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC0 0x03
21#define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC1 0x04
22#define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC2 0x05
23#define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC3 0x06
24#define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC4 0x07
25#define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC5 0x08
26#define CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPCS 0x09
27
28#define CTRL_CLK_CLK_FREQ_CONTROLLER_MASK_UNICAST_GPC \
29 (BIT(CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC0) | \
30 BIT(CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC1) | \
31 BIT(CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC2) | \
32 BIT(CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC3) | \
33 BIT(CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC4) | \
34 BIT(CTRL_CLK_CLK_FREQ_CONTROLLER_ID_GPC5))
35
36#define CTRL_CLK_CLK_FREQ_CONTROLLER_TYPE_DISABLED 0x00
37#define CTRL_CLK_CLK_FREQ_CONTROLLER_TYPE_PI 0x01
38
39
40struct clk_freq_controller {
41 struct boardobj super;
42 u8 controller_id;
43 u8 parts_freq_mode;
44 bool bdisable;
45 u32 clk_domain;
46 s16 freq_cap_noise_unaware_vmin_above;
47 s16 freq_cap_noise_unaware_vmin_below;
48 s16 freq_hyst_pos_mhz;
49 s16 freq_hyst_neg_mhz;
50};
51
52struct clk_freq_controller_pi {
53 struct clk_freq_controller super;
54 s32 prop_gain;
55 s32 integ_gain;
56 s32 integ_decay;
57 s32 volt_delta_min;
58 s32 volt_delta_max;
59 u8 slowdown_pct_min;
60 bool bpoison;
61};
62
63struct clk_freq_controllers {
64 struct boardobjgrp_e32 super;
65 u32 sampling_period_ms;
66 struct boardobjgrpmask_e32 freq_ctrl_load_mask;
67 u8 volt_policy_idx;
68 void *pprereq_load;
69};
70
71u32 clk_freq_controller_sw_setup(struct gk20a *g);
72u32 clk_freq_controller_pmu_setup(struct gk20a *g);
73
74#endif
diff --git a/drivers/gpu/nvgpu/include/bios.h b/drivers/gpu/nvgpu/include/bios.h
index 02991db9..f3939d14 100644
--- a/drivers/gpu/nvgpu/include/bios.h
+++ b/drivers/gpu/nvgpu/include/bios.h
@@ -842,4 +842,87 @@ struct therm_channel_1x_entry {
842#define NV_VBIOS_THERM_CHANNEL_1X_ENTRY_PARAM1_DEVICE_PROVIDER_INDEX_MASK 0xFF 842#define NV_VBIOS_THERM_CHANNEL_1X_ENTRY_PARAM1_DEVICE_PROVIDER_INDEX_MASK 0xFF
843#define NV_VBIOS_THERM_CHANNEL_1X_ENTRY_PARAM1_DEVICE_PROVIDER_INDEX_SHIFT 0 843#define NV_VBIOS_THERM_CHANNEL_1X_ENTRY_PARAM1_DEVICE_PROVIDER_INDEX_SHIFT 0
844 844
845/* Frequency Controller Table */
846struct vbios_fct_1x_header {
847 u8 version;
848 u8 header_size;
849 u8 entry_size;
850 u8 entry_count;
851 u16 sampling_period_ms;
852} __packed;
853
854struct vbios_fct_1x_entry {
855 u8 flags0;
856 u8 clk_domain_idx;
857 u16 param0;
858 u16 param1;
859 u32 param2;
860 u32 param3;
861 u32 param4;
862 u32 param5;
863 u32 param6;
864 u32 param7;
865 u32 param8;
866} __packed;
867
868#define NV_VBIOS_FCT_1X_ENTRY_FLAGS0_TYPE_MASK GENMASK(3, 0)
869#define NV_VBIOS_FCT_1X_ENTRY_FLAGS0_TYPE_SHIFT 0
870#define NV_VBIOS_FCT_1X_ENTRY_FLAGS0_TYPE_DISABLED 0x0
871#define NV_VBIOS_FCT_1X_ENTRY_FLAGS0_TYPE_PI 0x1
872
873#define NV_VBIOS_FCT_1X_ENTRY_PARAM0_ID_MASK GENMASK(7, 0)
874#define NV_VBIOS_FCT_1X_ENTRY_PARAM0_ID_SHIFT 0
875#define NV_VBIOS_FCT_1X_ENTRY_PARAM0_ID_SYS 0x00
876#define NV_VBIOS_FCT_1X_ENTRY_PARAM0_ID_LTC 0x01
877#define NV_VBIOS_FCT_1X_ENTRY_PARAM0_ID_XBAR 0x02
878#define NV_VBIOS_FCT_1X_ENTRY_PARAM0_ID_GPC0 0x03
879#define NV_VBIOS_FCT_1X_ENTRY_PARAM0_ID_GPC1 0x04
880#define NV_VBIOS_FCT_1X_ENTRY_PARAM0_ID_GPC2 0x05
881#define NV_VBIOS_FCT_1X_ENTRY_PARAM0_ID_GPC3 0x06
882#define NV_VBIOS_FCT_1X_ENTRY_PARAM0_ID_GPC4 0x07
883#define NV_VBIOS_FCT_1X_ENTRY_PARAM0_ID_GPC5 0x08
884#define NV_VBIOS_FCT_1X_ENTRY_PARAM0_ID_GPCS 0x09
885
886#define NV_VBIOS_FCT_1X_ENTRY_PARAM0_FREQ_MODE_MASK GENMASK(9, 8)
887#define NV_VBIOS_FCT_1X_ENTRY_PARAM0_FREQ_MODE_SHIFT 8
888#define NV_VBIOS_FCT_1X_ENTRY_PARAM0_FREQ_MODE_BCAST 0x0
889#define NV_VBIOS_FCT_1X_ENTRY_PARAM0_FREQ_MODE_MIN 0x1
890#define NV_VBIOS_FCT_1X_ENTRY_PARAM0_FREQ_MODE_MAX 0x2
891#define NV_VBIOS_FCT_1X_ENTRY_PARAM0_FREQ_MODE_AVG 0x3
892
893#define NV_VBIOS_FCT_1X_ENTRY_PARAM1_SLOWDOWN_PCT_MIN_MASK GENMASK(7, 0)
894#define NV_VBIOS_FCT_1X_ENTRY_PARAM1_SLOWDOWN_PCT_MIN_SHIFT 0
895
896#define NV_VBIOS_FCT_1X_ENTRY_PARAM1_POISON_MASK GENMASK(8, 8)
897#define NV_VBIOS_FCT_1X_ENTRY_PARAM1_POISON_SHIFT 8
898#define NV_VBIOS_FCT_1X_ENTRY_PARAM1_POISON_NO 0x0
899#define NV_VBIOS_FCT_1X_ENTRY_PARAM1_POISON_YES 0x1
900
901#define NV_VBIOS_FCT_1X_ENTRY_PARAM2_PROP_GAIN_MASK GENMASK(31, 0)
902#define NV_VBIOS_FCT_1X_ENTRY_PARAM2_PROP_GAIN_SHIFT 0
903
904#define NV_VBIOS_FCT_1X_ENTRY_PARAM3_INTEG_GAIN_MASK GENMASK(31, 0)
905#define NV_VBIOS_FCT_1X_ENTRY_PARAM3_INTEG_GAIN_SHIFT 0
906
907
908#define NV_VBIOS_FCT_1X_ENTRY_PARAM4_INTEG_DECAY_MASK GENMASK(31, 0)
909#define NV_VBIOS_FCT_1X_ENTRY_PARAM4_INTEG_DECAY_SHIFT 0
910
911#define NV_VBIOS_FCT_1X_ENTRY_PARAM5_VOLT_DELTA_MIN_MASK GENMASK(31, 0)
912#define NV_VBIOS_FCT_1X_ENTRY_PARAM5_VOLT_DELTA_MIN_SHIFT 0
913
914
915#define NV_VBIOS_FCT_1X_ENTRY_PARAM6_VOLT_DELTA_MAX_MASK GENMASK(31, 0)
916#define NV_VBIOS_FCT_1X_ENTRY_PARAM6_VOLT_DELTA_MAX_SHIFT 0
917
918#define NV_VBIOS_FCT_1X_ENTRY_PARAM7_FREQ_CAP_VF_MASK GENMASK(15, 0)
919#define NV_VBIOS_FCT_1X_ENTRY_PARAM7_FREQ_CAP_VF_SHIFT 0
920#define NV_VBIOS_FCT_1X_ENTRY_PARAM7_FREQ_CAP_VMIN_MASK GENMASK(31, 16)
921#define NV_VBIOS_FCT_1X_ENTRY_PARAM7_FREQ_CAP_VMIN_SHIFT 16
922
923#define NV_VBIOS_FCT_1X_ENTRY_PARAM8_FREQ_HYST_POS_MASK GENMASK(15, 0)
924#define NV_VBIOS_FCT_1X_ENTRY_PARAM8_FREQ_HYST_POS_SHIFT 0
925#define NV_VBIOS_FCT_1X_ENTRY_PARAM8_FREQ_HYST_NEG_MASK GENMASK(31, 16)
926#define NV_VBIOS_FCT_1X_ENTRY_PARAM8_FREQ_HYST_NEG_SHIFT 16
927
845#endif 928#endif
diff --git a/drivers/gpu/nvgpu/pstate/pstate.c b/drivers/gpu/nvgpu/pstate/pstate.c
index cf758023..cca6c445 100644
--- a/drivers/gpu/nvgpu/pstate/pstate.c
+++ b/drivers/gpu/nvgpu/pstate/pstate.c
@@ -79,6 +79,11 @@ int gk20a_init_pstate_support(struct gk20a *g)
79 return err; 79 return err;
80 80
81 err = pmgr_domain_sw_setup(g); 81 err = pmgr_domain_sw_setup(g);
82 if (err)
83 return err;
84
85 err = clk_freq_controller_sw_setup(g);
86
82 return err; 87 return err;
83} 88}
84 89
@@ -141,6 +146,10 @@ int gk20a_init_pstate_pmu_support(struct gk20a *g)
141 if (err) 146 if (err)
142 return err; 147 return err;
143 148
149 err = clk_freq_controller_pmu_setup(g);
150 if (err)
151 return err;
152
144 err = clk_pmu_vin_load(g); 153 err = clk_pmu_vin_load(g);
145 if (err) 154 if (err)
146 return err; 155 return err;