summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/pmgr/pwrdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/pmgr/pwrdev.c')
-rw-r--r--drivers/gpu/nvgpu/pmgr/pwrdev.c315
1 files changed, 315 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/pmgr/pwrdev.c b/drivers/gpu/nvgpu/pmgr/pwrdev.c
new file mode 100644
index 00000000..7f4ab716
--- /dev/null
+++ b/drivers/gpu/nvgpu/pmgr/pwrdev.c
@@ -0,0 +1,315 @@
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 "pwrdev.h"
27#include "boardobj/boardobjgrp.h"
28#include "boardobj/boardobjgrp_e32.h"
29#include "gp106/bios_gp106.h"
30
31static u32 _pwr_device_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_device_desc_table *ppmgrdevice =
37 (struct nv_pmu_pmgr_pwr_device_desc_table *)pmuboardobjgrp;
38
39 gk20a_dbg_info("");
40
41 /*check whether pmuboardobjgrp has a valid boardobj in index*/
42 if (((u32)BIT(idx) &
43 ppmgrdevice->hdr.data.super.obj_mask.super.data[0]) == 0)
44 return -EINVAL;
45
46 *ppboardobjpmudata = (struct nv_pmu_boardobj *)
47 &ppmgrdevice->devices[idx].data.board_obj;
48
49 gk20a_dbg_info(" Done");
50
51 return 0;
52}
53
54static u32 _pwr_domains_pmudatainit_ina3221(struct gk20a *g,
55 struct boardobj *board_obj_ptr,
56 struct nv_pmu_boardobj *ppmudata)
57{
58 struct nv_pmu_pmgr_pwr_device_desc_ina3221 *ina3221_desc;
59 struct pwr_device_ina3221 *ina3221;
60 u32 status = 0;
61 u32 indx;
62
63 status = boardobj_pmudatainit_super(g, board_obj_ptr, ppmudata);
64 if (status) {
65 nvgpu_err(g,
66 "error updating pmu boardobjgrp for pwr domain 0x%x",
67 status);
68 goto done;
69 }
70
71 ina3221 = (struct pwr_device_ina3221 *)board_obj_ptr;
72 ina3221_desc = (struct nv_pmu_pmgr_pwr_device_desc_ina3221 *) ppmudata;
73
74 ina3221_desc->super.power_corr_factor = ina3221->super.power_corr_factor;
75 ina3221_desc->i2c_dev_idx = ina3221->super.i2c_dev_idx;
76 ina3221_desc->configuration = ina3221->configuration;
77 ina3221_desc->mask_enable = ina3221->mask_enable;
78 /* configure NV_PMU_THERM_EVENT_EXT_OVERT */
79 ina3221_desc->event_mask = (1 << 0);
80 ina3221_desc->curr_correct_m = ina3221->curr_correct_m;
81 ina3221_desc->curr_correct_b = ina3221->curr_correct_b;
82
83 for (indx = 0; indx < NV_PMU_PMGR_PWR_DEVICE_INA3221_CH_NUM; indx++) {
84 ina3221_desc->r_shuntm_ohm[indx] = ina3221->r_shuntm_ohm[indx];
85 }
86
87done:
88 return status;
89}
90
91static struct boardobj *construct_pwr_device(struct gk20a *g,
92 void *pargs, u16 pargs_size, u8 type)
93{
94 struct boardobj *board_obj_ptr = NULL;
95 u32 status;
96 u32 indx;
97 struct pwr_device_ina3221 *pwrdev;
98 struct pwr_device_ina3221 *ina3221 = (struct pwr_device_ina3221*)pargs;
99
100 status = boardobj_construct_super(g, &board_obj_ptr,
101 pargs_size, pargs);
102 if (status)
103 return NULL;
104
105 pwrdev = (struct pwr_device_ina3221*)board_obj_ptr;
106
107 /* Set Super class interfaces */
108 board_obj_ptr->pmudatainit = _pwr_domains_pmudatainit_ina3221;
109 pwrdev->super.power_rail = ina3221->super.power_rail;
110 pwrdev->super.i2c_dev_idx = ina3221->super.i2c_dev_idx;
111 pwrdev->super.power_corr_factor = (1 << 12);
112 pwrdev->super.bIs_inforom_config = false;
113
114 /* Set INA3221-specific information */
115 pwrdev->configuration = ina3221->configuration;
116 pwrdev->mask_enable = ina3221->mask_enable;
117 pwrdev->gpio_function = ina3221->gpio_function;
118 pwrdev->curr_correct_m = ina3221->curr_correct_m;
119 pwrdev->curr_correct_b = ina3221->curr_correct_b;
120
121 for (indx = 0; indx < NV_PMU_PMGR_PWR_DEVICE_INA3221_CH_NUM; indx++) {
122 pwrdev->r_shuntm_ohm[indx] = ina3221->r_shuntm_ohm[indx];
123 }
124
125 gk20a_dbg_info(" Done");
126
127 return board_obj_ptr;
128}
129
130static u32 devinit_get_pwr_device_table(struct gk20a *g,
131 struct pwr_devices *ppwrdeviceobjs)
132{
133 u32 status = 0;
134 u8 *pwr_device_table_ptr = NULL;
135 u8 *curr_pwr_device_table_ptr = NULL;
136 struct boardobj *boardobj;
137 struct pwr_sensors_2x_header pwr_sensor_table_header = { 0 };
138 struct pwr_sensors_2x_entry pwr_sensor_table_entry = { 0 };
139 u32 index;
140 u32 obj_index = 0;
141 u16 pwr_device_size;
142 union {
143 struct boardobj boardobj;
144 struct pwr_device pwrdev;
145 struct pwr_device_ina3221 ina3221;
146 } pwr_device_data;
147
148 gk20a_dbg_info("");
149
150 pwr_device_table_ptr = (u8 *)nvgpu_bios_get_perf_table_ptrs(g,
151 g->bios.perf_token, POWER_SENSORS_TABLE);
152 if (pwr_device_table_ptr == NULL) {
153 status = -EINVAL;
154 goto done;
155 }
156
157 memcpy(&pwr_sensor_table_header, pwr_device_table_ptr,
158 VBIOS_POWER_SENSORS_2X_HEADER_SIZE_08);
159
160 if (pwr_sensor_table_header.version !=
161 VBIOS_POWER_SENSORS_VERSION_2X) {
162 status = -EINVAL;
163 goto done;
164 }
165
166 if (pwr_sensor_table_header.header_size <
167 VBIOS_POWER_SENSORS_2X_HEADER_SIZE_08) {
168 status = -EINVAL;
169 goto done;
170 }
171
172 if (pwr_sensor_table_header.table_entry_size !=
173 VBIOS_POWER_SENSORS_2X_ENTRY_SIZE_15) {
174 status = -EINVAL;
175 goto done;
176 }
177
178 curr_pwr_device_table_ptr = (pwr_device_table_ptr +
179 VBIOS_POWER_SENSORS_2X_HEADER_SIZE_08);
180
181 for (index = 0; index < pwr_sensor_table_header.num_table_entries; index++) {
182 bool use_fxp8_8 = false;
183 u8 i2c_dev_idx;
184 u8 device_type;
185
186 curr_pwr_device_table_ptr += (pwr_sensor_table_header.table_entry_size * index);
187
188 pwr_sensor_table_entry.flags0 = *curr_pwr_device_table_ptr;
189
190 memcpy(&pwr_sensor_table_entry.class_param0,
191 (curr_pwr_device_table_ptr + 1),
192 (VBIOS_POWER_SENSORS_2X_ENTRY_SIZE_15 - 1));
193
194 device_type = (u8)BIOS_GET_FIELD(
195 pwr_sensor_table_entry.flags0,
196 NV_VBIOS_POWER_SENSORS_2X_ENTRY_FLAGS0_CLASS);
197
198 if (device_type == NV_VBIOS_POWER_SENSORS_2X_ENTRY_FLAGS0_CLASS_I2C) {
199 i2c_dev_idx = (u8)BIOS_GET_FIELD(
200 pwr_sensor_table_entry.class_param0,
201 NV_VBIOS_POWER_SENSORS_2X_ENTRY_CLASS_PARAM0_I2C_INDEX);
202 use_fxp8_8 = (u8)BIOS_GET_FIELD(
203 pwr_sensor_table_entry.class_param0,
204 NV_VBIOS_POWER_SENSORS_2X_ENTRY_CLASS_PARAM0_I2C_USE_FXP8_8);
205
206 pwr_device_data.ina3221.super.i2c_dev_idx = i2c_dev_idx;
207 pwr_device_data.ina3221.r_shuntm_ohm[0].use_fxp8_8 = use_fxp8_8;
208 pwr_device_data.ina3221.r_shuntm_ohm[1].use_fxp8_8 = use_fxp8_8;
209 pwr_device_data.ina3221.r_shuntm_ohm[2].use_fxp8_8 = use_fxp8_8;
210 pwr_device_data.ina3221.r_shuntm_ohm[0].rshunt_value =
211 (u16)BIOS_GET_FIELD(
212 pwr_sensor_table_entry.sensor_param0,
213 NV_VBIOS_POWER_SENSORS_2X_ENTRY_SENSOR_PARAM0_INA3221_RSHUNT0_MOHM);
214
215 pwr_device_data.ina3221.r_shuntm_ohm[1].rshunt_value =
216 (u16)BIOS_GET_FIELD(
217 pwr_sensor_table_entry.sensor_param0,
218 NV_VBIOS_POWER_SENSORS_2X_ENTRY_SENSOR_PARAM0_INA3221_RSHUNT1_MOHM);
219
220 pwr_device_data.ina3221.r_shuntm_ohm[2].rshunt_value =
221 (u16)BIOS_GET_FIELD(
222 pwr_sensor_table_entry.sensor_param1,
223 NV_VBIOS_POWER_SENSORS_2X_ENTRY_SENSOR_PARAM1_INA3221_RSHUNT2_MOHM);
224 pwr_device_data.ina3221.configuration =
225 (u16)BIOS_GET_FIELD(
226 pwr_sensor_table_entry.sensor_param1,
227 NV_VBIOS_POWER_SENSORS_2X_ENTRY_SENSOR_PARAM1_INA3221_CONFIGURATION);
228
229 pwr_device_data.ina3221.mask_enable =
230 (u16)BIOS_GET_FIELD(
231 pwr_sensor_table_entry.sensor_param2,
232 NV_VBIOS_POWER_SENSORS_2X_ENTRY_SENSOR_PARAM2_INA3221_MASKENABLE);
233
234 pwr_device_data.ina3221.gpio_function =
235 (u8)BIOS_GET_FIELD(
236 pwr_sensor_table_entry.sensor_param2,
237 NV_VBIOS_POWER_SENSORS_2X_ENTRY_SENSOR_PARAM2_INA3221_GPIOFUNCTION);
238
239 pwr_device_data.ina3221.curr_correct_m =
240 (u16)BIOS_GET_FIELD(
241 pwr_sensor_table_entry.sensor_param3,
242 NV_VBIOS_POWER_SENSORS_2X_ENTRY_SENSOR_PARAM3_INA3221_CURR_CORRECT_M);
243
244 pwr_device_data.ina3221.curr_correct_b =
245 (u16)BIOS_GET_FIELD(
246 pwr_sensor_table_entry.sensor_param3,
247 NV_VBIOS_POWER_SENSORS_2X_ENTRY_SENSOR_PARAM3_INA3221_CURR_CORRECT_B);
248
249 if (!pwr_device_data.ina3221.curr_correct_m) {
250 pwr_device_data.ina3221.curr_correct_m = (1 << 12);
251 }
252 pwr_device_size = sizeof(struct pwr_device_ina3221);
253 } else
254 continue;
255
256 pwr_device_data.boardobj.type = CTRL_PMGR_PWR_DEVICE_TYPE_INA3221;
257 pwr_device_data.pwrdev.power_rail = (u8)0;
258
259 boardobj = construct_pwr_device(g, &pwr_device_data,
260 pwr_device_size, pwr_device_data.boardobj.type);
261
262 if (!boardobj) {
263 nvgpu_err(g,
264 "unable to create pwr device for %d type %d", index, pwr_device_data.boardobj.type);
265 status = -EINVAL;
266 goto done;
267 }
268
269 status = boardobjgrp_objinsert(&ppwrdeviceobjs->super.super,
270 boardobj, obj_index);
271
272 if (status) {
273 nvgpu_err(g,
274 "unable to insert pwr device boardobj for %d", index);
275 status = -EINVAL;
276 goto done;
277 }
278
279 ++obj_index;
280 }
281
282done:
283 gk20a_dbg_info(" done status %x", status);
284 return status;
285}
286
287u32 pmgr_device_sw_setup(struct gk20a *g)
288{
289 u32 status;
290 struct boardobjgrp *pboardobjgrp = NULL;
291 struct pwr_devices *ppwrdeviceobjs;
292
293 /* Construct the Super Class and override the Interfaces */
294 status = boardobjgrpconstruct_e32(g, &g->pmgr_pmu.pmgr_deviceobjs.super);
295 if (status) {
296 nvgpu_err(g,
297 "error creating boardobjgrp for pmgr devices, status - 0x%x",
298 status);
299 goto done;
300 }
301
302 pboardobjgrp = &g->pmgr_pmu.pmgr_deviceobjs.super.super;
303 ppwrdeviceobjs = &(g->pmgr_pmu.pmgr_deviceobjs);
304
305 /* Override the Interfaces */
306 pboardobjgrp->pmudatainstget = _pwr_device_pmudata_instget;
307
308 status = devinit_get_pwr_device_table(g, ppwrdeviceobjs);
309 if (status)
310 goto done;
311
312done:
313 gk20a_dbg_info(" done status %x", status);
314 return status;
315}