diff options
Diffstat (limited to 'include/pmgr/pwrmonitor.c')
-rw-r--r-- | include/pmgr/pwrmonitor.c | 376 |
1 files changed, 0 insertions, 376 deletions
diff --git a/include/pmgr/pwrmonitor.c b/include/pmgr/pwrmonitor.c deleted file mode 100644 index 710ae85..0000000 --- a/include/pmgr/pwrmonitor.c +++ /dev/null | |||
@@ -1,376 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016-2018, 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 | #include <nvgpu/gk20a.h> | ||
25 | |||
26 | #include "pwrdev.h" | ||
27 | #include "boardobj/boardobjgrp.h" | ||
28 | #include "boardobj/boardobjgrp_e32.h" | ||
29 | #include "gp106/bios_gp106.h" | ||
30 | |||
31 | static int _pwr_channel_pmudata_instget(struct gk20a *g, | ||
32 | struct nv_pmu_boardobjgrp *pmuboardobjgrp, | ||
33 | struct nv_pmu_boardobj **ppboardobjpmudata, | ||
34 | u8 idx) | ||
35 | { | ||
36 | struct nv_pmu_pmgr_pwr_channel_desc *ppmgrchannel = | ||
37 | (struct nv_pmu_pmgr_pwr_channel_desc *)pmuboardobjgrp; | ||
38 | |||
39 | nvgpu_log_info(g, " "); | ||
40 | |||
41 | /*check whether pmuboardobjgrp has a valid boardobj in index*/ | ||
42 | if (((u32)BIT(idx) & | ||
43 | ppmgrchannel->hdr.data.super.obj_mask.super.data[0]) == 0U) { | ||
44 | return -EINVAL; | ||
45 | } | ||
46 | |||
47 | *ppboardobjpmudata = (struct nv_pmu_boardobj *) | ||
48 | &ppmgrchannel->channels[idx].data.board_obj; | ||
49 | |||
50 | /* handle Global/common data here as we need index */ | ||
51 | ppmgrchannel->channels[idx].data.pwr_channel.ch_idx = idx; | ||
52 | |||
53 | nvgpu_log_info(g, " Done"); | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static int _pwr_channel_rels_pmudata_instget(struct gk20a *g, | ||
59 | struct nv_pmu_boardobjgrp *pmuboardobjgrp, | ||
60 | struct nv_pmu_boardobj **ppboardobjpmudata, | ||
61 | u8 idx) | ||
62 | { | ||
63 | struct nv_pmu_pmgr_pwr_chrelationship_desc *ppmgrchrels = | ||
64 | (struct nv_pmu_pmgr_pwr_chrelationship_desc *)pmuboardobjgrp; | ||
65 | |||
66 | nvgpu_log_info(g, " "); | ||
67 | |||
68 | /*check whether pmuboardobjgrp has a valid boardobj in index*/ | ||
69 | if (((u32)BIT(idx) & | ||
70 | ppmgrchrels->hdr.data.super.obj_mask.super.data[0]) == 0U) { | ||
71 | return -EINVAL; | ||
72 | } | ||
73 | |||
74 | *ppboardobjpmudata = (struct nv_pmu_boardobj *) | ||
75 | &ppmgrchrels->ch_rels[idx].data.board_obj; | ||
76 | |||
77 | nvgpu_log_info(g, " Done"); | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static u32 _pwr_channel_state_init(struct gk20a *g) | ||
83 | { | ||
84 | u8 indx = 0; | ||
85 | struct pwr_channel *pchannel; | ||
86 | u32 objmask = | ||
87 | g->pmgr_pmu.pmgr_monitorobjs.pwr_channels.super.objmask; | ||
88 | |||
89 | /* Initialize each PWR_CHANNEL's dependent channel mask */ | ||
90 | BOARDOBJGRP_FOR_EACH_INDEX_IN_MASK(32, indx, objmask) { | ||
91 | pchannel = PMGR_PWR_MONITOR_GET_PWR_CHANNEL(g, indx); | ||
92 | if (pchannel == NULL) { | ||
93 | nvgpu_err(g, | ||
94 | "PMGR_PWR_MONITOR_GET_PWR_CHANNEL-failed %d", indx); | ||
95 | return -EINVAL; | ||
96 | } | ||
97 | pchannel->dependent_ch_mask =0; | ||
98 | } | ||
99 | BOARDOBJGRP_FOR_EACH_INDEX_IN_MASK_END | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static bool _pwr_channel_implements(struct pwr_channel *pchannel, | ||
105 | u8 type) | ||
106 | { | ||
107 | return (type == BOARDOBJ_GET_TYPE(pchannel)); | ||
108 | } | ||
109 | |||
110 | static int _pwr_domains_pmudatainit_sensor(struct gk20a *g, | ||
111 | struct boardobj *board_obj_ptr, | ||
112 | struct nv_pmu_boardobj *ppmudata) | ||
113 | { | ||
114 | struct nv_pmu_pmgr_pwr_channel_sensor *pmu_sensor_data; | ||
115 | struct pwr_channel_sensor *sensor; | ||
116 | int status = 0; | ||
117 | |||
118 | status = boardobj_pmudatainit_super(g, board_obj_ptr, ppmudata); | ||
119 | if (status) { | ||
120 | nvgpu_err(g, | ||
121 | "error updating pmu boardobjgrp for pwr sensor 0x%x", | ||
122 | status); | ||
123 | goto done; | ||
124 | } | ||
125 | |||
126 | sensor = (struct pwr_channel_sensor *)board_obj_ptr; | ||
127 | pmu_sensor_data = (struct nv_pmu_pmgr_pwr_channel_sensor *) ppmudata; | ||
128 | |||
129 | pmu_sensor_data->super.pwr_rail = sensor->super.pwr_rail; | ||
130 | pmu_sensor_data->super.volt_fixedu_v = sensor->super.volt_fixed_uv; | ||
131 | pmu_sensor_data->super.pwr_corr_slope = sensor->super.pwr_corr_slope; | ||
132 | pmu_sensor_data->super.pwr_corr_offsetm_w = sensor->super.pwr_corr_offset_mw; | ||
133 | pmu_sensor_data->super.curr_corr_slope = sensor->super.curr_corr_slope; | ||
134 | pmu_sensor_data->super.curr_corr_offsetm_a = sensor->super.curr_corr_offset_ma; | ||
135 | pmu_sensor_data->super.dependent_ch_mask = sensor->super.dependent_ch_mask; | ||
136 | pmu_sensor_data->super.ch_idx = 0; | ||
137 | |||
138 | pmu_sensor_data->pwr_dev_idx = sensor->pwr_dev_idx; | ||
139 | pmu_sensor_data->pwr_dev_prov_idx = sensor->pwr_dev_prov_idx; | ||
140 | |||
141 | done: | ||
142 | return status; | ||
143 | } | ||
144 | |||
145 | static struct boardobj *construct_pwr_topology(struct gk20a *g, | ||
146 | void *pargs, u16 pargs_size, u8 type) | ||
147 | { | ||
148 | struct boardobj *board_obj_ptr = NULL; | ||
149 | int status; | ||
150 | struct pwr_channel_sensor *pwrchannel; | ||
151 | struct pwr_channel_sensor *sensor = (struct pwr_channel_sensor*)pargs; | ||
152 | |||
153 | status = boardobj_construct_super(g, &board_obj_ptr, | ||
154 | pargs_size, pargs); | ||
155 | if (status) { | ||
156 | return NULL; | ||
157 | } | ||
158 | |||
159 | pwrchannel = (struct pwr_channel_sensor*)board_obj_ptr; | ||
160 | |||
161 | /* Set Super class interfaces */ | ||
162 | board_obj_ptr->pmudatainit = _pwr_domains_pmudatainit_sensor; | ||
163 | |||
164 | pwrchannel->super.pwr_rail = sensor->super.pwr_rail; | ||
165 | pwrchannel->super.volt_fixed_uv = sensor->super.volt_fixed_uv; | ||
166 | pwrchannel->super.pwr_corr_slope = sensor->super.pwr_corr_slope; | ||
167 | pwrchannel->super.pwr_corr_offset_mw = sensor->super.pwr_corr_offset_mw; | ||
168 | pwrchannel->super.curr_corr_slope = sensor->super.curr_corr_slope; | ||
169 | pwrchannel->super.curr_corr_offset_ma = sensor->super.curr_corr_offset_ma; | ||
170 | pwrchannel->super.dependent_ch_mask = 0; | ||
171 | |||
172 | pwrchannel->pwr_dev_idx = sensor->pwr_dev_idx; | ||
173 | pwrchannel->pwr_dev_prov_idx = sensor->pwr_dev_prov_idx; | ||
174 | |||
175 | nvgpu_log_info(g, " Done"); | ||
176 | |||
177 | return board_obj_ptr; | ||
178 | } | ||
179 | |||
180 | static int devinit_get_pwr_topology_table(struct gk20a *g, | ||
181 | struct pmgr_pwr_monitor *ppwrmonitorobjs) | ||
182 | { | ||
183 | int status = 0; | ||
184 | u8 *pwr_topology_table_ptr = NULL; | ||
185 | u8 *curr_pwr_topology_table_ptr = NULL; | ||
186 | struct boardobj *boardobj; | ||
187 | struct pwr_topology_2x_header pwr_topology_table_header = { 0 }; | ||
188 | struct pwr_topology_2x_entry pwr_topology_table_entry = { 0 }; | ||
189 | u32 index; | ||
190 | u32 obj_index = 0; | ||
191 | u16 pwr_topology_size; | ||
192 | union { | ||
193 | struct boardobj boardobj; | ||
194 | struct pwr_channel pwrchannel; | ||
195 | struct pwr_channel_sensor sensor; | ||
196 | } pwr_topology_data; | ||
197 | |||
198 | nvgpu_log_info(g, " "); | ||
199 | |||
200 | pwr_topology_table_ptr = (u8 *)nvgpu_bios_get_perf_table_ptrs(g, | ||
201 | g->bios.perf_token, POWER_TOPOLOGY_TABLE); | ||
202 | if (pwr_topology_table_ptr == NULL) { | ||
203 | status = -EINVAL; | ||
204 | goto done; | ||
205 | } | ||
206 | |||
207 | memcpy(&pwr_topology_table_header, pwr_topology_table_ptr, | ||
208 | VBIOS_POWER_TOPOLOGY_2X_HEADER_SIZE_06); | ||
209 | |||
210 | if (pwr_topology_table_header.version != | ||
211 | VBIOS_POWER_TOPOLOGY_VERSION_2X) { | ||
212 | status = -EINVAL; | ||
213 | goto done; | ||
214 | } | ||
215 | |||
216 | g->pmgr_pmu.pmgr_monitorobjs.b_is_topology_tbl_ver_1x = false; | ||
217 | |||
218 | if (pwr_topology_table_header.header_size < | ||
219 | VBIOS_POWER_TOPOLOGY_2X_HEADER_SIZE_06) { | ||
220 | status = -EINVAL; | ||
221 | goto done; | ||
222 | } | ||
223 | |||
224 | if (pwr_topology_table_header.table_entry_size != | ||
225 | VBIOS_POWER_TOPOLOGY_2X_ENTRY_SIZE_16) { | ||
226 | status = -EINVAL; | ||
227 | goto done; | ||
228 | } | ||
229 | |||
230 | curr_pwr_topology_table_ptr = (pwr_topology_table_ptr + | ||
231 | VBIOS_POWER_TOPOLOGY_2X_HEADER_SIZE_06); | ||
232 | |||
233 | for (index = 0; index < pwr_topology_table_header.num_table_entries; | ||
234 | index++) { | ||
235 | u8 class_type; | ||
236 | |||
237 | curr_pwr_topology_table_ptr += (pwr_topology_table_header.table_entry_size * index); | ||
238 | |||
239 | pwr_topology_table_entry.flags0 = *curr_pwr_topology_table_ptr; | ||
240 | pwr_topology_table_entry.pwr_rail = *(curr_pwr_topology_table_ptr + 1); | ||
241 | |||
242 | memcpy(&pwr_topology_table_entry.param0, | ||
243 | (curr_pwr_topology_table_ptr + 2), | ||
244 | (VBIOS_POWER_TOPOLOGY_2X_ENTRY_SIZE_16 - 2U)); | ||
245 | |||
246 | class_type = (u8)BIOS_GET_FIELD( | ||
247 | pwr_topology_table_entry.flags0, | ||
248 | NV_VBIOS_POWER_TOPOLOGY_2X_ENTRY_FLAGS0_CLASS); | ||
249 | |||
250 | if (class_type == NV_VBIOS_POWER_TOPOLOGY_2X_ENTRY_FLAGS0_CLASS_SENSOR) { | ||
251 | pwr_topology_data.sensor.pwr_dev_idx = (u8)BIOS_GET_FIELD( | ||
252 | pwr_topology_table_entry.param1, | ||
253 | NV_VBIOS_POWER_TOPOLOGY_2X_ENTRY_PARAM1_SENSOR_INDEX); | ||
254 | pwr_topology_data.sensor.pwr_dev_prov_idx = (u8)BIOS_GET_FIELD( | ||
255 | pwr_topology_table_entry.param1, | ||
256 | NV_VBIOS_POWER_TOPOLOGY_2X_ENTRY_PARAM1_SENSOR_PROVIDER_INDEX); | ||
257 | |||
258 | pwr_topology_size = sizeof(struct pwr_channel_sensor); | ||
259 | } else { | ||
260 | continue; | ||
261 | } | ||
262 | |||
263 | /* Initialize data for the parent class */ | ||
264 | pwr_topology_data.boardobj.type = CTRL_PMGR_PWR_CHANNEL_TYPE_SENSOR; | ||
265 | pwr_topology_data.pwrchannel.pwr_rail = (u8)pwr_topology_table_entry.pwr_rail; | ||
266 | pwr_topology_data.pwrchannel.volt_fixed_uv = pwr_topology_table_entry.param0; | ||
267 | pwr_topology_data.pwrchannel.pwr_corr_slope = (1 << 12); | ||
268 | pwr_topology_data.pwrchannel.pwr_corr_offset_mw = 0; | ||
269 | pwr_topology_data.pwrchannel.curr_corr_slope = | ||
270 | (u32)pwr_topology_table_entry.curr_corr_slope; | ||
271 | pwr_topology_data.pwrchannel.curr_corr_offset_ma = | ||
272 | (s32)pwr_topology_table_entry.curr_corr_offset; | ||
273 | |||
274 | boardobj = construct_pwr_topology(g, &pwr_topology_data, | ||
275 | pwr_topology_size, pwr_topology_data.boardobj.type); | ||
276 | |||
277 | if (!boardobj) { | ||
278 | nvgpu_err(g, | ||
279 | "unable to create pwr topology for %d type %d", | ||
280 | index, pwr_topology_data.boardobj.type); | ||
281 | status = -EINVAL; | ||
282 | goto done; | ||
283 | } | ||
284 | |||
285 | status = boardobjgrp_objinsert(&ppwrmonitorobjs->pwr_channels.super, | ||
286 | boardobj, obj_index); | ||
287 | |||
288 | if (status) { | ||
289 | nvgpu_err(g, | ||
290 | "unable to insert pwr topology boardobj for %d", index); | ||
291 | status = -EINVAL; | ||
292 | goto done; | ||
293 | } | ||
294 | |||
295 | ++obj_index; | ||
296 | } | ||
297 | |||
298 | done: | ||
299 | nvgpu_log_info(g, " done status %x", status); | ||
300 | return status; | ||
301 | } | ||
302 | |||
303 | int pmgr_monitor_sw_setup(struct gk20a *g) | ||
304 | { | ||
305 | int status; | ||
306 | struct boardobjgrp *pboardobjgrp = NULL; | ||
307 | struct pwr_channel *pchannel; | ||
308 | struct pmgr_pwr_monitor *ppwrmonitorobjs; | ||
309 | u8 indx = 0; | ||
310 | |||
311 | /* Construct the Super Class and override the Interfaces */ | ||
312 | status = boardobjgrpconstruct_e32(g, | ||
313 | &g->pmgr_pmu.pmgr_monitorobjs.pwr_channels); | ||
314 | if (status) { | ||
315 | nvgpu_err(g, | ||
316 | "error creating boardobjgrp for pmgr channel, status - 0x%x", | ||
317 | status); | ||
318 | goto done; | ||
319 | } | ||
320 | |||
321 | pboardobjgrp = &(g->pmgr_pmu.pmgr_monitorobjs.pwr_channels.super); | ||
322 | |||
323 | /* Override the Interfaces */ | ||
324 | pboardobjgrp->pmudatainstget = _pwr_channel_pmudata_instget; | ||
325 | |||
326 | /* Construct the Super Class and override the Interfaces */ | ||
327 | status = boardobjgrpconstruct_e32(g, | ||
328 | &g->pmgr_pmu.pmgr_monitorobjs.pwr_ch_rels); | ||
329 | if (status) { | ||
330 | nvgpu_err(g, | ||
331 | "error creating boardobjgrp for pmgr channel relationship, status - 0x%x", | ||
332 | status); | ||
333 | goto done; | ||
334 | } | ||
335 | |||
336 | pboardobjgrp = &(g->pmgr_pmu.pmgr_monitorobjs.pwr_ch_rels.super); | ||
337 | |||
338 | /* Override the Interfaces */ | ||
339 | pboardobjgrp->pmudatainstget = _pwr_channel_rels_pmudata_instget; | ||
340 | |||
341 | /* Initialize the Total GPU Power Channel Mask to 0 */ | ||
342 | g->pmgr_pmu.pmgr_monitorobjs.pmu_data.channels.hdr.data.total_gpu_power_channel_mask = 0; | ||
343 | g->pmgr_pmu.pmgr_monitorobjs.total_gpu_channel_idx = | ||
344 | CTRL_PMGR_PWR_CHANNEL_INDEX_INVALID; | ||
345 | |||
346 | /* Supported topology table version 1.0 */ | ||
347 | g->pmgr_pmu.pmgr_monitorobjs.b_is_topology_tbl_ver_1x = true; | ||
348 | |||
349 | ppwrmonitorobjs = &(g->pmgr_pmu.pmgr_monitorobjs); | ||
350 | |||
351 | status = devinit_get_pwr_topology_table(g, ppwrmonitorobjs); | ||
352 | if (status) { | ||
353 | goto done; | ||
354 | } | ||
355 | |||
356 | status = _pwr_channel_state_init(g); | ||
357 | if (status) { | ||
358 | goto done; | ||
359 | } | ||
360 | |||
361 | /* Initialise physicalChannelMask */ | ||
362 | g->pmgr_pmu.pmgr_monitorobjs.physical_channel_mask = 0; | ||
363 | |||
364 | pboardobjgrp = &g->pmgr_pmu.pmgr_monitorobjs.pwr_channels.super; | ||
365 | |||
366 | BOARDOBJGRP_FOR_EACH(pboardobjgrp, struct pwr_channel *, pchannel, indx) { | ||
367 | if (_pwr_channel_implements(pchannel, | ||
368 | CTRL_PMGR_PWR_CHANNEL_TYPE_SENSOR)) { | ||
369 | g->pmgr_pmu.pmgr_monitorobjs.physical_channel_mask |= BIT(indx); | ||
370 | } | ||
371 | } | ||
372 | |||
373 | done: | ||
374 | nvgpu_log_info(g, " done status %x", status); | ||
375 | return status; | ||
376 | } | ||