summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/therm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/therm')
-rw-r--r--drivers/gpu/nvgpu/therm/thrm.c54
-rw-r--r--drivers/gpu/nvgpu/therm/thrm.h38
-rw-r--r--drivers/gpu/nvgpu/therm/thrmchannel.c253
-rw-r--r--drivers/gpu/nvgpu/therm/thrmchannel.h51
-rw-r--r--drivers/gpu/nvgpu/therm/thrmdev.c200
-rw-r--r--drivers/gpu/nvgpu/therm/thrmdev.h40
-rw-r--r--drivers/gpu/nvgpu/therm/thrmpmu.c270
-rw-r--r--drivers/gpu/nvgpu/therm/thrmpmu.h31
8 files changed, 937 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/therm/thrm.c b/drivers/gpu/nvgpu/therm/thrm.c
new file mode 100644
index 00000000..8b35b466
--- /dev/null
+++ b/drivers/gpu/nvgpu/therm/thrm.c
@@ -0,0 +1,54 @@
1/*
2 * Copyright (c) 2016, 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 "gk20a/gk20a.h"
24#include "thrm.h"
25#include "thrmpmu.h"
26
27u32 therm_domain_sw_setup(struct gk20a *g)
28{
29 u32 status;
30
31 status = therm_device_sw_setup(g);
32 if (status) {
33 nvgpu_err(g,
34 "error creating boardobjgrp for therm devices, status - 0x%x",
35 status);
36 goto exit;
37 }
38
39 status = therm_channel_sw_setup(g);
40 if (status) {
41 nvgpu_err(g,
42 "error creating boardobjgrp for therm channel, status - 0x%x",
43 status);
44 goto exit;
45 }
46
47exit:
48 return status;
49}
50
51u32 therm_domain_pmu_setup(struct gk20a *g)
52{
53 return therm_send_pmgr_tables_to_pmu(g);
54}
diff --git a/drivers/gpu/nvgpu/therm/thrm.h b/drivers/gpu/nvgpu/therm/thrm.h
new file mode 100644
index 00000000..5b5a5a57
--- /dev/null
+++ b/drivers/gpu/nvgpu/therm/thrm.h
@@ -0,0 +1,38 @@
1/*
2 * general thermal table structures & definitions
3 *
4 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24#ifndef _THRM_H_
25#define _THRM_H_
26
27#include "thrmdev.h"
28#include "thrmchannel.h"
29
30struct therm_pmupstate {
31 struct therm_devices therm_deviceobjs;
32 struct therm_channels therm_channelobjs;
33};
34
35u32 therm_domain_sw_setup(struct gk20a *g);
36u32 therm_domain_pmu_setup(struct gk20a *g);
37
38#endif
diff --git a/drivers/gpu/nvgpu/therm/thrmchannel.c b/drivers/gpu/nvgpu/therm/thrmchannel.c
new file mode 100644
index 00000000..f8be8430
--- /dev/null
+++ b/drivers/gpu/nvgpu/therm/thrmchannel.c
@@ -0,0 +1,253 @@
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 "thrmchannel.h"
28#include "boardobj/boardobjgrp.h"
29#include "boardobj/boardobjgrp_e32.h"
30#include "gp106/bios_gp106.h"
31
32static u32 _therm_channel_pmudatainit_device(struct gk20a *g,
33 struct boardobj *board_obj_ptr,
34 struct nv_pmu_boardobj *ppmudata)
35{
36 u32 status = 0;
37 struct therm_channel *pchannel;
38 struct therm_channel_device *ptherm_channel;
39 struct nv_pmu_therm_therm_channel_device_boardobj_set *pset;
40
41 status = boardobj_pmudatainit_super(g, board_obj_ptr, ppmudata);
42 if (status) {
43 nvgpu_err(g,
44 "error updating pmu boardobjgrp for therm channel 0x%x",
45 status);
46 status = -ENOMEM;
47 goto done;
48 }
49
50 pchannel = (struct therm_channel *)board_obj_ptr;
51 pset = (struct nv_pmu_therm_therm_channel_device_boardobj_set *)ppmudata;
52 ptherm_channel = (struct therm_channel_device *)board_obj_ptr;
53
54 pset->super.scaling = pchannel->scaling;
55 pset->super.offset = pchannel->offset;
56 pset->super.temp_min = pchannel->temp_min;
57 pset->super.temp_max = pchannel->temp_max;
58
59 pset->therm_dev_idx = ptherm_channel->therm_dev_idx;
60 pset->therm_dev_prov_idx = ptherm_channel->therm_dev_prov_idx;
61
62done:
63 return status;
64}
65static struct boardobj *construct_channel_device(struct gk20a *g,
66 void *pargs, u16 pargs_size, u8 type)
67{
68 struct boardobj *board_obj_ptr = NULL;
69 struct therm_channel *pchannel;
70 struct therm_channel_device *pchannel_device;
71 u32 status;
72 struct therm_channel_device *therm_device = (struct therm_channel_device*)pargs;
73
74 status = boardobj_construct_super(g, &board_obj_ptr,
75 pargs_size, pargs);
76 if (status)
77 return NULL;
78
79 /* Set Super class interfaces */
80 board_obj_ptr->pmudatainit = _therm_channel_pmudatainit_device;
81
82 pchannel = (struct therm_channel *)board_obj_ptr;
83 pchannel_device = (struct therm_channel_device *)board_obj_ptr;
84
85 g->ops.therm.get_internal_sensor_limits(&pchannel->temp_max,
86 &pchannel->temp_min);
87 pchannel->scaling = (1 << 8);
88 pchannel->offset = 0;
89
90 pchannel_device->therm_dev_idx = therm_device->therm_dev_idx;
91 pchannel_device->therm_dev_prov_idx = therm_device->therm_dev_prov_idx;
92
93 gk20a_dbg_info(" Done");
94
95 return board_obj_ptr;
96}
97
98static u32 _therm_channel_pmudata_instget(struct gk20a *g,
99 struct nv_pmu_boardobjgrp *pmuboardobjgrp,
100 struct nv_pmu_boardobj **ppboardobjpmudata,
101 u8 idx)
102{
103 struct nv_pmu_therm_therm_channel_boardobj_grp_set *pgrp_set =
104 (struct nv_pmu_therm_therm_channel_boardobj_grp_set *)
105 pmuboardobjgrp;
106
107 gk20a_dbg_info("");
108
109 /*check whether pmuboardobjgrp has a valid boardobj in index*/
110 if (((u32)BIT(idx) &
111 pgrp_set->hdr.data.super.obj_mask.super.data[0]) == 0)
112 return -EINVAL;
113
114 *ppboardobjpmudata = (struct nv_pmu_boardobj *)
115 &pgrp_set->objects[idx].data.board_obj;
116
117 gk20a_dbg_info(" Done");
118
119 return 0;
120}
121
122static u32 devinit_get_therm_channel_table(struct gk20a *g,
123 struct therm_channels *pthermchannelobjs)
124{
125 u32 status = 0;
126 u8 *therm_channel_table_ptr = NULL;
127 u8 *curr_therm_channel_table_ptr = NULL;
128 struct boardobj *boardobj;
129 struct therm_channel_1x_header therm_channel_table_header = { 0 };
130 struct therm_channel_1x_entry *therm_channel_table_entry = NULL;
131 u32 index;
132 u32 obj_index = 0;
133 u16 therm_channel_size = 0;
134 union {
135 struct boardobj boardobj;
136 struct therm_channel therm_channel;
137 struct therm_channel_device device;
138 } therm_channel_data;
139
140 gk20a_dbg_info("");
141
142 therm_channel_table_ptr = (u8 *)nvgpu_bios_get_perf_table_ptrs(g,
143 g->bios.perf_token, THERMAL_CHANNEL_TABLE);
144 if (therm_channel_table_ptr == NULL) {
145 status = -EINVAL;
146 goto done;
147 }
148
149 memcpy(&therm_channel_table_header, therm_channel_table_ptr,
150 VBIOS_THERM_CHANNEL_1X_HEADER_SIZE_09);
151
152 if (therm_channel_table_header.version !=
153 VBIOS_THERM_CHANNEL_VERSION_1X) {
154 status = -EINVAL;
155 goto done;
156 }
157
158 if (therm_channel_table_header.header_size <
159 VBIOS_THERM_CHANNEL_1X_HEADER_SIZE_09) {
160 status = -EINVAL;
161 goto done;
162 }
163
164 curr_therm_channel_table_ptr = (therm_channel_table_ptr +
165 VBIOS_THERM_CHANNEL_1X_HEADER_SIZE_09);
166
167 for (index = 0; index < therm_channel_table_header.num_table_entries;
168 index++) {
169 therm_channel_table_entry = (struct therm_channel_1x_entry *)
170 (curr_therm_channel_table_ptr +
171 (therm_channel_table_header.table_entry_size * index));
172
173 if (therm_channel_table_entry->class_id !=
174 NV_VBIOS_THERM_CHANNEL_1X_ENTRY_CLASS_DEVICE) {
175 continue;
176 }
177
178 therm_channel_data.device.therm_dev_idx = therm_channel_table_entry->param0;
179 therm_channel_data.device.therm_dev_prov_idx = therm_channel_table_entry->param1;
180
181 therm_channel_size = sizeof(struct therm_channel_device);
182 therm_channel_data.boardobj.type = CTRL_THERMAL_THERM_CHANNEL_CLASS_DEVICE;
183
184 boardobj = construct_channel_device(g, &therm_channel_data,
185 therm_channel_size, therm_channel_data.boardobj.type);
186
187 if (!boardobj) {
188 nvgpu_err(g,
189 "unable to create thermal device for %d type %d",
190 index, therm_channel_data.boardobj.type);
191 status = -EINVAL;
192 goto done;
193 }
194
195 status = boardobjgrp_objinsert(&pthermchannelobjs->super.super,
196 boardobj, obj_index);
197
198 if (status) {
199 nvgpu_err(g,
200 "unable to insert thermal device boardobj for %d", index);
201 status = -EINVAL;
202 goto done;
203 }
204
205 ++obj_index;
206 }
207
208done:
209 gk20a_dbg_info(" done status %x", status);
210 return status;
211}
212
213u32 therm_channel_sw_setup(struct gk20a *g)
214{
215 u32 status;
216 struct boardobjgrp *pboardobjgrp = NULL;
217 struct therm_channels *pthermchannelobjs;
218
219 /* Construct the Super Class and override the Interfaces */
220 status = boardobjgrpconstruct_e32(g,
221 &g->therm_pmu.therm_channelobjs.super);
222 if (status) {
223 nvgpu_err(g,
224 "error creating boardobjgrp for therm devices, status - 0x%x",
225 status);
226 goto done;
227 }
228
229 pboardobjgrp = &g->therm_pmu.therm_channelobjs.super.super;
230 pthermchannelobjs = &(g->therm_pmu.therm_channelobjs);
231
232 /* Override the Interfaces */
233 pboardobjgrp->pmudatainstget = _therm_channel_pmudata_instget;
234
235 status = devinit_get_therm_channel_table(g, pthermchannelobjs);
236 if (status)
237 goto done;
238
239 BOARDOBJGRP_PMU_CONSTRUCT(pboardobjgrp, THERM, THERM_CHANNEL);
240
241 status = BOARDOBJGRP_PMU_CMD_GRP_SET_CONSTRUCT(g, pboardobjgrp,
242 therm, THERM, therm_channel, THERM_CHANNEL);
243 if (status) {
244 nvgpu_err(g,
245 "error constructing PMU_BOARDOBJ_CMD_GRP_SET interface - 0x%x",
246 status);
247 goto done;
248 }
249
250done:
251 gk20a_dbg_info(" done status %x", status);
252 return status;
253}
diff --git a/drivers/gpu/nvgpu/therm/thrmchannel.h b/drivers/gpu/nvgpu/therm/thrmchannel.h
new file mode 100644
index 00000000..4e0dd2e4
--- /dev/null
+++ b/drivers/gpu/nvgpu/therm/thrmchannel.h
@@ -0,0 +1,51 @@
1/*
2 * general thermal device structures & definitions
3 *
4 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24#ifndef _THRMCHANNEL_H_
25#define _THRMCHANNEL_H_
26
27#include "boardobj/boardobj.h"
28#include "boardobj/boardobjgrp.h"
29#include "ctrl/ctrltherm.h"
30
31struct therm_channel {
32 struct boardobj super;
33 s16 scaling;
34 s16 offset;
35 s32 temp_min;
36 s32 temp_max;
37};
38
39struct therm_channels {
40 struct boardobjgrp_e32 super;
41};
42
43struct therm_channel_device {
44 struct therm_channel super;
45 u8 therm_dev_idx;
46 u8 therm_dev_prov_idx;
47};
48
49u32 therm_channel_sw_setup(struct gk20a *g);
50
51#endif
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}
diff --git a/drivers/gpu/nvgpu/therm/thrmdev.h b/drivers/gpu/nvgpu/therm/thrmdev.h
new file mode 100644
index 00000000..83ff5cbf
--- /dev/null
+++ b/drivers/gpu/nvgpu/therm/thrmdev.h
@@ -0,0 +1,40 @@
1/*
2 * general thermal device structures & definitions
3 *
4 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24#ifndef _THRMDEV_H_
25#define _THRMDEV_H_
26
27#include "boardobj/boardobj.h"
28#include "boardobj/boardobjgrp.h"
29
30struct therm_devices {
31 struct boardobjgrp_e32 super;
32};
33
34struct therm_device {
35 struct therm_devices super;
36};
37
38u32 therm_device_sw_setup(struct gk20a *g);
39
40#endif
diff --git a/drivers/gpu/nvgpu/therm/thrmpmu.c b/drivers/gpu/nvgpu/therm/thrmpmu.c
new file mode 100644
index 00000000..6a79cc3e
--- /dev/null
+++ b/drivers/gpu/nvgpu/therm/thrmpmu.c
@@ -0,0 +1,270 @@
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 "gk20a/gk20a.h"
24#include "boardobj/boardobjgrp.h"
25#include "boardobj/boardobjgrp_e32.h"
26#include "thrmpmu.h"
27#include <nvgpu/pmuif/nvgpu_gpmu_cmdif.h>
28
29struct therm_pmucmdhandler_params {
30 struct nv_pmu_therm_rpc *prpccall;
31 u32 success;
32};
33
34static void therm_pmucmdhandler(struct gk20a *g, struct pmu_msg *msg,
35 void *param, u32 handle, u32 status)
36{
37 struct therm_pmucmdhandler_params *phandlerparams =
38 (struct therm_pmucmdhandler_params *)param;
39
40 if (msg->msg.therm.msg_type != NV_PMU_THERM_MSG_ID_RPC) {
41 nvgpu_err(g, "unknow msg %x",
42 msg->msg.pmgr.msg_type);
43 return;
44 }
45
46 if (!phandlerparams->prpccall->b_supported)
47 nvgpu_err(g, "RPC msg %x failed",
48 msg->msg.pmgr.msg_type);
49 else
50 phandlerparams->success = 1;
51}
52
53u32 therm_send_pmgr_tables_to_pmu(struct gk20a *g)
54{
55 u32 status = 0;
56 struct boardobjgrp *pboardobjgrp = NULL;
57
58 if (!BOARDOBJGRP_IS_EMPTY(&g->therm_pmu.therm_deviceobjs.super.super)) {
59 pboardobjgrp = &g->therm_pmu.therm_deviceobjs.super.super;
60 status = pboardobjgrp->pmuinithandle(g, pboardobjgrp);
61 if (status) {
62 nvgpu_err(g,
63 "therm_send_pmgr_tables_to_pmu - therm_device failed %x",
64 status);
65 goto exit;
66 }
67 }
68
69 if (!BOARDOBJGRP_IS_EMPTY(
70 &g->therm_pmu.therm_channelobjs.super.super)) {
71 pboardobjgrp = &g->therm_pmu.therm_channelobjs.super.super;
72 status = pboardobjgrp->pmuinithandle(g, pboardobjgrp);
73 if (status) {
74 nvgpu_err(g,
75 "therm_send_pmgr_tables_to_pmu - therm_channel failed %x",
76 status);
77 goto exit;
78 }
79 }
80
81exit:
82 return status;
83}
84
85static u32 therm_pmu_cmd_post(struct gk20a *g, struct pmu_cmd *cmd,
86 struct pmu_msg *msg, struct pmu_payload *payload,
87 u32 queue_id, pmu_callback callback, void* cb_param,
88 u32 *seq_desc, unsigned long timeout)
89{
90 u32 status;
91 struct therm_pmucmdhandler_params *handlerparams = NULL;
92
93 status = nvgpu_pmu_cmd_post(g, cmd, msg, payload,
94 queue_id,
95 callback,
96 cb_param,
97 seq_desc,
98 timeout);
99 if (status) {
100 nvgpu_err(g,
101 "unable to post therm cmd for unit %x cmd id %x size %x",
102 cmd->hdr.unit_id, cmd->cmd.therm.cmd_type, cmd->hdr.size);
103 goto exit;
104 }
105
106 if (cb_param) {
107 handlerparams = (struct therm_pmucmdhandler_params*)cb_param;
108
109 pmu_wait_message_cond(&g->pmu,
110 gk20a_get_gr_idle_timeout(g),
111 &handlerparams->success, 1);
112
113 if (handlerparams->success == 0) {
114 nvgpu_err(g, "could not process cmd");
115 status = -ETIMEDOUT;
116 goto exit;
117 }
118 }
119
120exit:
121 return status;
122}
123
124static u32 therm_set_warn_temp_limit(struct gk20a *g)
125{
126 u32 seqdesc = 0;
127 struct pmu_cmd cmd;
128 struct pmu_msg msg;
129 struct pmu_payload payload;
130 struct nv_pmu_therm_rpc rpccall;
131 struct therm_pmucmdhandler_params handlerparams;
132
133 memset(&payload, 0, sizeof(struct pmu_payload));
134 memset(&cmd, 0, sizeof(struct pmu_cmd));
135 memset(&msg, 0, sizeof(struct pmu_msg));
136 memset(&rpccall, 0, sizeof(struct nv_pmu_therm_rpc));
137 memset(&handlerparams, 0, sizeof(struct therm_pmucmdhandler_params));
138
139 rpccall.function = NV_PMU_THERM_RPC_ID_SLCT_EVENT_TEMP_TH_SET;
140 rpccall.params.slct_event_temp_th_set.event_id =
141 NV_PMU_THERM_EVENT_THERMAL_1;
142 rpccall.params.slct_event_temp_th_set.temp_threshold = g->curr_warn_temp;
143 rpccall.b_supported = 0;
144
145 cmd.hdr.unit_id = PMU_UNIT_THERM;
146 cmd.hdr.size = ((u32)sizeof(struct nv_pmu_therm_cmd_rpc) +
147 (u32)sizeof(struct pmu_hdr));
148 cmd.cmd.therm.cmd_type = NV_PMU_THERM_CMD_ID_RPC;
149
150 msg.hdr.size = sizeof(struct pmu_msg);
151
152 payload.in.buf = (u8 *)&rpccall;
153 payload.in.size = (u32)sizeof(struct nv_pmu_therm_rpc);
154 payload.in.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED;
155 payload.in.offset = NV_PMU_THERM_CMD_RPC_ALLOC_OFFSET;
156
157 payload.out.buf = (u8 *)&rpccall;
158 payload.out.size = (u32)sizeof(struct nv_pmu_therm_rpc);
159 payload.out.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED;
160 payload.out.offset = NV_PMU_CLK_MSG_RPC_ALLOC_OFFSET;
161
162 /* Setup the handler params to communicate back results.*/
163 handlerparams.success = 0;
164 handlerparams.prpccall = &rpccall;
165
166 return therm_pmu_cmd_post(g, &cmd, NULL, &payload,
167 PMU_COMMAND_QUEUE_LPQ,
168 therm_pmucmdhandler,
169 (void *)&handlerparams,
170 &seqdesc, ~0);
171}
172
173static u32 therm_enable_slct_notification_request(struct gk20a *g)
174{
175 u32 seqdesc = 0;
176 struct pmu_cmd cmd = { {0} };
177
178 cmd.hdr.unit_id = PMU_UNIT_THERM;
179 cmd.hdr.size = ((u32)sizeof(struct nv_pmu_therm_cmd_hw_slowdown_notification) +
180 (u32)sizeof(struct pmu_hdr));
181
182 cmd.cmd.therm.cmd_type = NV_PMU_THERM_CMD_ID_HW_SLOWDOWN_NOTIFICATION;
183 cmd.cmd.therm.hw_slct_notification.request =
184 NV_RM_PMU_THERM_HW_SLOWDOWN_NOTIFICATION_REQUEST_ENABLE;
185
186 return therm_pmu_cmd_post(g, &cmd, NULL, NULL,
187 PMU_COMMAND_QUEUE_LPQ,
188 NULL,
189 NULL,
190 &seqdesc, ~0);
191}
192
193static u32 therm_send_slct_configuration_to_pmu(struct gk20a *g)
194{
195 u32 seqdesc = 0;
196 struct pmu_cmd cmd;
197 struct pmu_msg msg;
198 struct pmu_payload payload;
199 struct nv_pmu_therm_rpc rpccall;
200 struct therm_pmucmdhandler_params handlerparams;
201
202 memset(&payload, 0, sizeof(struct pmu_payload));
203 memset(&cmd, 0, sizeof(struct pmu_cmd));
204 memset(&msg, 0, sizeof(struct pmu_msg));
205 memset(&rpccall, 0, sizeof(struct nv_pmu_therm_rpc));
206 memset(&handlerparams, 0, sizeof(struct therm_pmucmdhandler_params));
207
208 rpccall.function = NV_PMU_THERM_RPC_ID_SLCT;
209 rpccall.params.slct.mask_enabled =
210 (1 << NV_PMU_THERM_EVENT_THERMAL_1);
211 rpccall.b_supported = 0;
212
213 cmd.hdr.unit_id = PMU_UNIT_THERM;
214 cmd.hdr.size = ((u32)sizeof(struct nv_pmu_therm_cmd_rpc) +
215 (u32)sizeof(struct pmu_hdr));
216 cmd.cmd.therm.cmd_type = NV_PMU_THERM_CMD_ID_RPC;
217
218 msg.hdr.size = sizeof(struct pmu_msg);
219
220 payload.in.buf = (u8 *)&rpccall;
221 payload.in.size = (u32)sizeof(struct nv_pmu_therm_rpc);
222 payload.in.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED;
223 payload.in.offset = NV_PMU_THERM_CMD_RPC_ALLOC_OFFSET;
224
225 payload.out.buf = (u8 *)&rpccall;
226 payload.out.size = (u32)sizeof(struct nv_pmu_therm_rpc);
227 payload.out.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED;
228 payload.out.offset = NV_PMU_CLK_MSG_RPC_ALLOC_OFFSET;
229
230 /* Setup the handler params to communicate back results.*/
231 handlerparams.success = 0;
232 handlerparams.prpccall = &rpccall;
233
234 return therm_pmu_cmd_post(g, &cmd, NULL, &payload,
235 PMU_COMMAND_QUEUE_LPQ,
236 therm_pmucmdhandler,
237 (void *)&handlerparams,
238 &seqdesc, ~0);
239}
240
241u32 therm_configure_therm_alert(struct gk20a *g)
242{
243 u32 status;
244
245 status = therm_enable_slct_notification_request(g);
246 if (status) {
247 nvgpu_err(g,
248 "therm_enable_slct_notification_request-failed %d",
249 status);
250 goto exit;
251 }
252
253 status = therm_send_slct_configuration_to_pmu(g);
254 if (status) {
255 nvgpu_err(g,
256 "therm_send_slct_configuration_to_pmu-failed %d",
257 status);
258 goto exit;
259 }
260
261 status = therm_set_warn_temp_limit(g);
262 if (status) {
263 nvgpu_err(g,
264 "therm_set_warn_temp_limit-failed %d",
265 status);
266 goto exit;
267 }
268exit:
269 return status;
270}
diff --git a/drivers/gpu/nvgpu/therm/thrmpmu.h b/drivers/gpu/nvgpu/therm/thrmpmu.h
new file mode 100644
index 00000000..1813ce6c
--- /dev/null
+++ b/drivers/gpu/nvgpu/therm/thrmpmu.h
@@ -0,0 +1,31 @@
1/*
2 * general thermal pmu control structures & definitions
3 *
4 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24#ifndef _THRMPMU_H_
25#define _THRMPMU_H_
26
27u32 therm_send_pmgr_tables_to_pmu(struct gk20a *g);
28
29u32 therm_configure_therm_alert(struct gk20a *g);
30
31#endif