summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/volt/volt_policy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/volt/volt_policy.c')
-rw-r--r--drivers/gpu/nvgpu/volt/volt_policy.c361
1 files changed, 361 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/volt/volt_policy.c b/drivers/gpu/nvgpu/volt/volt_policy.c
new file mode 100644
index 00000000..1e34b54f
--- /dev/null
+++ b/drivers/gpu/nvgpu/volt/volt_policy.c
@@ -0,0 +1,361 @@
1/*
2 * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 */
22
23#include <nvgpu/bios.h>
24
25#include "gk20a/gk20a.h"
26#include "boardobj/boardobjgrp.h"
27#include "boardobj/boardobjgrp_e32.h"
28#include "gp106/bios_gp106.h"
29#include "ctrl/ctrlvolt.h"
30
31#include "volt.h"
32
33static u32 volt_policy_pmu_data_init_super(struct gk20a *g,
34 struct boardobj *pboardobj, struct nv_pmu_boardobj *ppmudata)
35{
36 return boardobj_pmudatainit_super(g, pboardobj, ppmudata);
37}
38
39static u32 construct_volt_policy(struct gk20a *g,
40 struct boardobj **ppboardobj, u16 size, void *pArgs)
41{
42 struct voltage_policy *pvolt_policy = NULL;
43 u32 status = 0;
44
45 status = boardobj_construct_super(g, ppboardobj, size, pArgs);
46 if (status)
47 return status;
48
49 pvolt_policy = (struct voltage_policy *)*ppboardobj;
50
51 pvolt_policy->super.pmudatainit = volt_policy_pmu_data_init_super;
52
53 return status;
54}
55
56static u32 construct_volt_policy_split_rail(struct gk20a *g,
57 struct boardobj **ppboardobj, u16 size, void *pArgs)
58{
59 struct voltage_policy_split_rail *ptmp_policy =
60 (struct voltage_policy_split_rail *)pArgs;
61 struct voltage_policy_split_rail *pvolt_policy = NULL;
62 u32 status = 0;
63
64 status = construct_volt_policy(g, ppboardobj, size, pArgs);
65 if (status)
66 return status;
67
68 pvolt_policy = (struct voltage_policy_split_rail *)*ppboardobj;
69
70 pvolt_policy->rail_idx_master = ptmp_policy->rail_idx_master;
71 pvolt_policy->rail_idx_slave = ptmp_policy->rail_idx_slave;
72 pvolt_policy->delta_min_vfe_equ_idx =
73 ptmp_policy->delta_min_vfe_equ_idx;
74 pvolt_policy->delta_max_vfe_equ_idx =
75 ptmp_policy->delta_max_vfe_equ_idx;
76
77 return status;
78}
79
80static u32 volt_policy_pmu_data_init_split_rail(struct gk20a *g,
81 struct boardobj *pboardobj, struct nv_pmu_boardobj *ppmudata)
82{
83 u32 status = 0;
84 struct voltage_policy_split_rail *ppolicy;
85 struct nv_pmu_volt_volt_policy_splt_r_boardobj_set *pset;
86
87 status = volt_policy_pmu_data_init_super(g, pboardobj, ppmudata);
88 if (status)
89 goto done;
90
91 ppolicy = (struct voltage_policy_split_rail *)pboardobj;
92 pset = (struct nv_pmu_volt_volt_policy_splt_r_boardobj_set *)
93 ppmudata;
94
95 pset->rail_idx_master = ppolicy->rail_idx_master;
96 pset->rail_idx_slave = ppolicy->rail_idx_slave;
97 pset->delta_min_vfe_equ_idx = ppolicy->delta_min_vfe_equ_idx;
98 pset->delta_max_vfe_equ_idx = ppolicy->delta_max_vfe_equ_idx;
99 pset->offset_delta_min_uv = ppolicy->offset_delta_min_uv;
100 pset->offset_delta_max_uv = ppolicy->offset_delta_max_uv;
101
102done:
103 return status;
104}
105
106static u32 volt_construct_volt_policy_split_rail_single_step(struct gk20a *g,
107 struct boardobj **ppboardobj, u16 size, void *pargs)
108{
109 struct boardobj *pboardobj = NULL;
110 struct voltage_policy_split_rail_single_step *p_volt_policy = NULL;
111 u32 status = 0;
112
113 status = construct_volt_policy_split_rail(g, ppboardobj, size, pargs);
114 if (status)
115 return status;
116
117 pboardobj = (*ppboardobj);
118 p_volt_policy = (struct voltage_policy_split_rail_single_step *)
119 *ppboardobj;
120
121 pboardobj->pmudatainit = volt_policy_pmu_data_init_split_rail;
122
123 return status;
124}
125
126static struct voltage_policy *volt_volt_policy_construct(struct gk20a *g, void *pargs)
127{
128 struct boardobj *pboard_obj = NULL;
129 u32 status = 0;
130
131 if (BOARDOBJ_GET_TYPE(pargs) ==
132 CTRL_VOLT_POLICY_TYPE_SR_SINGLE_STEP) {
133 status = volt_construct_volt_policy_split_rail_single_step(g,
134 &pboard_obj,
135 sizeof(struct voltage_policy_split_rail_single_step),
136 pargs);
137 if (status) {
138 nvgpu_err(g,
139 "Could not allocate memory for voltage_policy");
140 pboard_obj = NULL;
141 }
142 }
143
144 return (struct voltage_policy *)pboard_obj;
145}
146
147static u8 volt_policy_type_convert(u8 vbios_type)
148{
149 switch (vbios_type) {
150 case NV_VBIOS_VOLTAGE_POLICY_1X_ENTRY_TYPE_SINGLE_RAIL:
151 return CTRL_VOLT_POLICY_TYPE_SINGLE_RAIL;
152
153 case NV_VBIOS_VOLTAGE_POLICY_1X_ENTRY_TYPE_SR_MULTI_STEP:
154 return CTRL_VOLT_POLICY_TYPE_SR_MULTI_STEP;
155
156 case NV_VBIOS_VOLTAGE_POLICY_1X_ENTRY_TYPE_SR_SINGLE_STEP:
157 return CTRL_VOLT_POLICY_TYPE_SR_SINGLE_STEP;
158 }
159
160 return CTRL_VOLT_POLICY_TYPE_INVALID;
161}
162
163static u32 volt_get_volt_policy_table(struct gk20a *g,
164 struct voltage_policy_metadata *pvolt_policy_metadata)
165{
166 u32 status = 0;
167 u8 *voltage_policy_table_ptr = NULL;
168 struct voltage_policy *ppolicy = NULL;
169 struct vbios_voltage_policy_table_1x_header header = { 0 };
170 struct vbios_voltage_policy_table_1x_entry entry = { 0 };
171 u8 i;
172 u8 policy_type = 0;
173 u8 *entry_offset;
174 union policy_type {
175 struct boardobj board_obj;
176 struct voltage_policy volt_policy;
177 struct voltage_policy_split_rail split_rail;
178 } policy_type_data;
179
180 voltage_policy_table_ptr =
181 (u8 *)nvgpu_bios_get_perf_table_ptrs(g,
182 g->bios.perf_token, VOLTAGE_POLICY_TABLE);
183 if (voltage_policy_table_ptr == NULL) {
184 status = -EINVAL;
185 goto done;
186 }
187
188 memcpy(&header, voltage_policy_table_ptr,
189 sizeof(struct vbios_voltage_policy_table_1x_header));
190
191 /* Set Voltage Policy Table Index for Perf Core VF Sequence client. */
192 pvolt_policy_metadata->perf_core_vf_seq_policy_idx =
193 (u8)header.perf_core_vf_seq_policy_idx;
194
195 /* Read in the entries. */
196 for (i = 0; i < header.num_table_entries; i++) {
197 entry_offset = (voltage_policy_table_ptr + header.header_size +
198 i * header.table_entry_size);
199
200 memcpy(&entry, entry_offset,
201 sizeof(struct vbios_voltage_policy_table_1x_entry));
202
203 memset(&policy_type_data, 0x0, sizeof(policy_type_data));
204
205 policy_type = volt_policy_type_convert((u8)entry.type);
206
207 if (policy_type == CTRL_VOLT_POLICY_TYPE_SR_SINGLE_STEP) {
208 policy_type_data.split_rail.rail_idx_master =
209 (u8)BIOS_GET_FIELD(entry.param0,
210 NV_VBIOS_VPT_ENTRY_PARAM0_SR_VD_MASTER);
211
212 policy_type_data.split_rail.rail_idx_slave =
213 (u8)BIOS_GET_FIELD(entry.param0,
214 NV_VBIOS_VPT_ENTRY_PARAM0_SR_VD_SLAVE);
215
216 policy_type_data.split_rail.delta_min_vfe_equ_idx =
217 (u8)BIOS_GET_FIELD(entry.param0,
218 NV_VBIOS_VPT_ENTRY_PARAM0_SR_DELTA_SM_MIN);
219
220 policy_type_data.split_rail.delta_max_vfe_equ_idx =
221 (u8)BIOS_GET_FIELD(entry.param0,
222 NV_VBIOS_VPT_ENTRY_PARAM0_SR_DELTA_SM_MAX);
223 }
224
225 policy_type_data.board_obj.type = policy_type;
226
227 ppolicy = volt_volt_policy_construct(g,
228 (void *)&policy_type_data);
229 if (ppolicy == NULL) {
230 nvgpu_err(g,
231 "Failure to construct VOLT_POLICY object.");
232 status = -EINVAL;
233 goto done;
234 }
235
236 status = boardobjgrp_objinsert(
237 &pvolt_policy_metadata->volt_policies.super,
238 (struct boardobj *)ppolicy, i);
239 if (status) {
240 nvgpu_err(g,
241 "could not add volt_policy for entry %d into boardobjgrp ",
242 i);
243 goto done;
244 }
245 }
246
247done:
248 return status;
249}
250static u32 _volt_policy_devgrp_pmudata_instget(struct gk20a *g,
251 struct nv_pmu_boardobjgrp *pmuboardobjgrp,
252 struct nv_pmu_boardobj **ppboardobjpmudata, u8 idx)
253{
254 struct nv_pmu_volt_volt_policy_boardobj_grp_set *pgrp_set =
255 (struct nv_pmu_volt_volt_policy_boardobj_grp_set *)
256 pmuboardobjgrp;
257
258 gk20a_dbg_info("");
259
260 /*check whether pmuboardobjgrp has a valid boardobj in index*/
261 if (((u32)BIT(idx) &
262 pgrp_set->hdr.data.super.obj_mask.super.data[0]) == 0)
263 return -EINVAL;
264
265 *ppboardobjpmudata = (struct nv_pmu_boardobj *)
266 &pgrp_set->objects[idx].data.board_obj;
267 gk20a_dbg_info(" Done");
268 return 0;
269}
270
271static u32 _volt_policy_devgrp_pmustatus_instget(struct gk20a *g,
272 void *pboardobjgrppmu,
273 struct nv_pmu_boardobj_query **ppboardobjpmustatus, u8 idx)
274{
275 struct nv_pmu_volt_volt_policy_boardobj_grp_get_status *p_get_status =
276 (struct nv_pmu_volt_volt_policy_boardobj_grp_get_status *)
277 pboardobjgrppmu;
278
279 /*check whether pmuboardobjgrp has a valid boardobj in index*/
280 if (((u32)BIT(idx) &
281 p_get_status->hdr.data.super.obj_mask.super.data[0]) == 0)
282 return -EINVAL;
283
284 *ppboardobjpmustatus = (struct nv_pmu_boardobj_query *)
285 &p_get_status->objects[idx].data.board_obj;
286 return 0;
287}
288
289u32 volt_policy_pmu_setup(struct gk20a *g)
290{
291 u32 status;
292 struct boardobjgrp *pboardobjgrp = NULL;
293
294 gk20a_dbg_info("");
295
296 pboardobjgrp =
297 &g->perf_pmu.volt.volt_policy_metadata.volt_policies.super;
298
299 if (!pboardobjgrp->bconstructed)
300 return -EINVAL;
301
302 status = pboardobjgrp->pmuinithandle(g, pboardobjgrp);
303
304 gk20a_dbg_info("Done");
305 return status;
306}
307
308u32 volt_policy_sw_setup(struct gk20a *g)
309{
310 u32 status = 0;
311 struct boardobjgrp *pboardobjgrp = NULL;
312
313 gk20a_dbg_info("");
314
315 status = boardobjgrpconstruct_e32(g,
316 &g->perf_pmu.volt.volt_policy_metadata.volt_policies);
317 if (status) {
318 nvgpu_err(g,
319 "error creating boardobjgrp for volt rail, status - 0x%x",
320 status);
321 goto done;
322 }
323
324 pboardobjgrp =
325 &g->perf_pmu.volt.volt_policy_metadata.volt_policies.super;
326
327 pboardobjgrp->pmudatainstget = _volt_policy_devgrp_pmudata_instget;
328 pboardobjgrp->pmustatusinstget = _volt_policy_devgrp_pmustatus_instget;
329
330 /* Obtain Voltage Rail Table from VBIOS */
331 status = volt_get_volt_policy_table(g, &g->perf_pmu.volt.
332 volt_policy_metadata);
333 if (status)
334 goto done;
335
336 /* Populate data for the VOLT_RAIL PMU interface */
337 BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, VOLT, VOLT_POLICY);
338
339 status = BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(g, pboardobjgrp,
340 volt, VOLT, volt_policy, VOLT_POLICY);
341 if (status) {
342 nvgpu_err(g,
343 "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x",
344 status);
345 goto done;
346 }
347
348 status = BOARDOBJGRP_PMU_CMD_GRP_GET_STATUS_CONSTRUCT(g,
349 &g->perf_pmu.volt.volt_policy_metadata.volt_policies.super,
350 volt, VOLT, volt_policy, VOLT_POLICY);
351 if (status) {
352 nvgpu_err(g,
353 "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x",
354 status);
355 goto done;
356 }
357
358done:
359 gk20a_dbg_info(" done status %x", status);
360 return status;
361}