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