summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/therm/thrmdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/therm/thrmdev.c')
-rw-r--r--drivers/gpu/nvgpu/therm/thrmdev.c200
1 files changed, 200 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/therm/thrmdev.c b/drivers/gpu/nvgpu/therm/thrmdev.c
new file mode 100644
index 00000000..1aff119c
--- /dev/null
+++ b/drivers/gpu/nvgpu/therm/thrmdev.c
@@ -0,0 +1,200 @@
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#include <nvgpu/pmuif/nvgpu_gpmu_cmdif.h>
25
26#include "gk20a/gk20a.h"
27#include "thrmdev.h"
28#include "boardobj/boardobjgrp.h"
29#include "boardobj/boardobjgrp_e32.h"
30#include "gp106/bios_gp106.h"
31#include "ctrl/ctrltherm.h"
32
33static struct boardobj *construct_therm_device(struct gk20a *g,
34 void *pargs, u16 pargs_size, u8 type)
35{
36 struct boardobj *board_obj_ptr = NULL;
37 u32 status;
38
39 status = boardobj_construct_super(g, &board_obj_ptr,
40 pargs_size, pargs);
41 if (status)
42 return NULL;
43
44 gk20a_dbg_info(" Done");
45
46 return board_obj_ptr;
47}
48
49static u32 _therm_device_pmudata_instget(struct gk20a *g,
50 struct nv_pmu_boardobjgrp *pmuboardobjgrp,
51 struct nv_pmu_boardobj **ppboardobjpmudata,
52 u8 idx)
53{
54 struct nv_pmu_therm_therm_device_boardobj_grp_set *pgrp_set =
55 (struct nv_pmu_therm_therm_device_boardobj_grp_set *)
56 pmuboardobjgrp;
57
58 gk20a_dbg_info("");
59
60 /*check whether pmuboardobjgrp has a valid boardobj in index*/
61 if (((u32)BIT(idx) &
62 pgrp_set->hdr.data.super.obj_mask.super.data[0]) == 0)
63 return -EINVAL;
64
65 *ppboardobjpmudata = (struct nv_pmu_boardobj *)
66 &pgrp_set->objects[idx].data;
67
68 gk20a_dbg_info(" Done");
69
70 return 0;
71}
72
73static u32 devinit_get_therm_device_table(struct gk20a *g,
74 struct therm_devices *pthermdeviceobjs)
75{
76 u32 status = 0;
77 u8 *therm_device_table_ptr = NULL;
78 u8 *curr_therm_device_table_ptr = NULL;
79 struct boardobj *boardobj;
80 struct therm_device_1x_header therm_device_table_header = { 0 };
81 struct therm_device_1x_entry *therm_device_table_entry = NULL;
82 u32 index;
83 u32 obj_index = 0;
84 u16 therm_device_size = 0;
85 union {
86 struct boardobj boardobj;
87 struct therm_device therm_device;
88 } therm_device_data;
89
90 gk20a_dbg_info("");
91
92 therm_device_table_ptr = (u8 *)nvgpu_bios_get_perf_table_ptrs(g,
93 g->bios.perf_token, THERMAL_DEVICE_TABLE);
94 if (therm_device_table_ptr == NULL) {
95 status = -EINVAL;
96 goto done;
97 }
98
99 memcpy(&therm_device_table_header, therm_device_table_ptr,
100 VBIOS_THERM_DEVICE_1X_HEADER_SIZE_04);
101
102 if (therm_device_table_header.version !=
103 VBIOS_THERM_DEVICE_VERSION_1X) {
104 status = -EINVAL;
105 goto done;
106 }
107
108 if (therm_device_table_header.header_size <
109 VBIOS_THERM_DEVICE_1X_HEADER_SIZE_04) {
110 status = -EINVAL;
111 goto done;
112 }
113
114 curr_therm_device_table_ptr = (therm_device_table_ptr +
115 VBIOS_THERM_DEVICE_1X_HEADER_SIZE_04);
116
117 for (index = 0; index < therm_device_table_header.num_table_entries;
118 index++) {
119 therm_device_table_entry = (struct therm_device_1x_entry *)
120 (curr_therm_device_table_ptr +
121 (therm_device_table_header.table_entry_size * index));
122
123 if (therm_device_table_entry->class_id !=
124 NV_VBIOS_THERM_DEVICE_1X_ENTRY_CLASS_GPU) {
125 continue;
126 }
127
128 therm_device_size = sizeof(struct therm_device);
129 therm_device_data.boardobj.type = CTRL_THERMAL_THERM_DEVICE_CLASS_GPU;
130
131 boardobj = construct_therm_device(g, &therm_device_data,
132 therm_device_size, therm_device_data.boardobj.type);
133
134 if (!boardobj) {
135 nvgpu_err(g,
136 "unable to create thermal device for %d type %d",
137 index, therm_device_data.boardobj.type);
138 status = -EINVAL;
139 goto done;
140 }
141
142 status = boardobjgrp_objinsert(&pthermdeviceobjs->super.super,
143 boardobj, obj_index);
144
145 if (status) {
146 nvgpu_err(g,
147 "unable to insert thermal device boardobj for %d", index);
148 status = -EINVAL;
149 goto done;
150 }
151
152 ++obj_index;
153 }
154
155done:
156 gk20a_dbg_info(" done status %x", status);
157 return status;
158}
159
160u32 therm_device_sw_setup(struct gk20a *g)
161{
162 u32 status;
163 struct boardobjgrp *pboardobjgrp = NULL;
164 struct therm_devices *pthermdeviceobjs;
165
166 /* Construct the Super Class and override the Interfaces */
167 status = boardobjgrpconstruct_e32(g,
168 &g->therm_pmu.therm_deviceobjs.super);
169 if (status) {
170 nvgpu_err(g,
171 "error creating boardobjgrp for therm devices, status - 0x%x",
172 status);
173 goto done;
174 }
175
176 pboardobjgrp = &g->therm_pmu.therm_deviceobjs.super.super;
177 pthermdeviceobjs = &(g->therm_pmu.therm_deviceobjs);
178
179 /* Override the Interfaces */
180 pboardobjgrp->pmudatainstget = _therm_device_pmudata_instget;
181
182 status = devinit_get_therm_device_table(g, pthermdeviceobjs);
183 if (status)
184 goto done;
185
186 BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, THERM, THERM_DEVICE);
187
188 status = BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(g, pboardobjgrp,
189 therm, THERM, therm_device, THERM_DEVICE);
190 if (status) {
191 nvgpu_err(g,
192 "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x",
193 status);
194 goto done;
195 }
196
197done:
198 gk20a_dbg_info(" done status %x", status);
199 return status;
200}