aboutsummaryrefslogtreecommitdiffstats
path: root/include/therm/thrmpmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'include/therm/thrmpmu.c')
-rw-r--r--include/therm/thrmpmu.c271
1 files changed, 271 insertions, 0 deletions
diff --git a/include/therm/thrmpmu.c b/include/therm/thrmpmu.c
new file mode 100644
index 0000000..65587ab
--- /dev/null
+++ b/include/therm/thrmpmu.c
@@ -0,0 +1,271 @@
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#include <nvgpu/gk20a.h>
23
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}
53
54int therm_send_pmgr_tables_to_pmu(struct gk20a *g)
55{
56 int status = 0;
57 struct boardobjgrp *pboardobjgrp = NULL;
58
59 if (!BOARDOBJGRP_IS_EMPTY(&g->therm_pmu.therm_deviceobjs.super.super)) {
60 pboardobjgrp = &g->therm_pmu.therm_deviceobjs.super.super;
61 status = pboardobjgrp->pmuinithandle(g, pboardobjgrp);
62 if (status) {
63 nvgpu_err(g,
64 "therm_send_pmgr_tables_to_pmu - therm_device failed %x",
65 status);
66 goto exit;
67 }
68 }
69
70 if (!BOARDOBJGRP_IS_EMPTY(
71 &g->therm_pmu.therm_channelobjs.super.super)) {
72 pboardobjgrp = &g->therm_pmu.therm_channelobjs.super.super;
73 status = pboardobjgrp->pmuinithandle(g, pboardobjgrp);
74 if (status) {
75 nvgpu_err(g,
76 "therm_send_pmgr_tables_to_pmu - therm_channel failed %x",
77 status);
78 goto exit;
79 }
80 }
81
82exit:
83 return status;
84}
85
86static u32 therm_pmu_cmd_post(struct gk20a *g, struct pmu_cmd *cmd,
87 struct pmu_msg *msg, struct pmu_payload *payload,
88 u32 queue_id, pmu_callback callback, void* cb_param,
89 u32 *seq_desc, unsigned long timeout)
90{
91 u32 status;
92 struct therm_pmucmdhandler_params *handlerparams = NULL;
93
94 status = nvgpu_pmu_cmd_post(g, cmd, msg, payload,
95 queue_id,
96 callback,
97 cb_param,
98 seq_desc,
99 timeout);
100 if (status) {
101 nvgpu_err(g,
102 "unable to post therm cmd for unit %x cmd id %x size %x",
103 cmd->hdr.unit_id, cmd->cmd.therm.cmd_type, cmd->hdr.size);
104 goto exit;
105 }
106
107 if (cb_param) {
108 handlerparams = (struct therm_pmucmdhandler_params*)cb_param;
109
110 pmu_wait_message_cond(&g->pmu,
111 gk20a_get_gr_idle_timeout(g),
112 &handlerparams->success, 1);
113
114 if (handlerparams->success == 0) {
115 nvgpu_err(g, "could not process cmd");
116 status = -ETIMEDOUT;
117 goto exit;
118 }
119 }
120
121exit:
122 return status;
123}
124
125static u32 therm_set_warn_temp_limit(struct gk20a *g)
126{
127 u32 seqdesc = 0;
128 struct pmu_cmd cmd;
129 struct pmu_msg msg;
130 struct pmu_payload payload;
131 struct nv_pmu_therm_rpc rpccall;
132 struct therm_pmucmdhandler_params handlerparams;
133
134 memset(&payload, 0, sizeof(struct pmu_payload));
135 memset(&cmd, 0, sizeof(struct pmu_cmd));
136 memset(&msg, 0, sizeof(struct pmu_msg));
137 memset(&rpccall, 0, sizeof(struct nv_pmu_therm_rpc));
138 memset(&handlerparams, 0, sizeof(struct therm_pmucmdhandler_params));
139
140 rpccall.function = NV_PMU_THERM_RPC_ID_SLCT_EVENT_TEMP_TH_SET;
141 rpccall.params.slct_event_temp_th_set.event_id =
142 NV_PMU_THERM_EVENT_THERMAL_1;
143 rpccall.params.slct_event_temp_th_set.temp_threshold = g->curr_warn_temp;
144 rpccall.b_supported = 0;
145
146 cmd.hdr.unit_id = PMU_UNIT_THERM;
147 cmd.hdr.size = ((u32)sizeof(struct nv_pmu_therm_cmd_rpc) +
148 (u32)sizeof(struct pmu_hdr));
149 cmd.cmd.therm.cmd_type = NV_PMU_THERM_CMD_ID_RPC;
150
151 msg.hdr.size = sizeof(struct pmu_msg);
152
153 payload.in.buf = (u8 *)&rpccall;
154 payload.in.size = (u32)sizeof(struct nv_pmu_therm_rpc);
155 payload.in.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED;
156 payload.in.offset = NV_PMU_THERM_CMD_RPC_ALLOC_OFFSET;
157
158 payload.out.buf = (u8 *)&rpccall;
159 payload.out.size = (u32)sizeof(struct nv_pmu_therm_rpc);
160 payload.out.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED;
161 payload.out.offset = NV_PMU_CLK_MSG_RPC_ALLOC_OFFSET;
162
163 /* Setup the handler params to communicate back results.*/
164 handlerparams.success = 0;
165 handlerparams.prpccall = &rpccall;
166
167 return therm_pmu_cmd_post(g, &cmd, NULL, &payload,
168 PMU_COMMAND_QUEUE_LPQ,
169 therm_pmucmdhandler,
170 (void *)&handlerparams,
171 &seqdesc, ~0);
172}
173
174static u32 therm_enable_slct_notification_request(struct gk20a *g)
175{
176 u32 seqdesc = 0;
177 struct pmu_cmd cmd = { {0} };
178
179 cmd.hdr.unit_id = PMU_UNIT_THERM;
180 cmd.hdr.size = ((u32)sizeof(struct nv_pmu_therm_cmd_hw_slowdown_notification) +
181 (u32)sizeof(struct pmu_hdr));
182
183 cmd.cmd.therm.cmd_type = NV_PMU_THERM_CMD_ID_HW_SLOWDOWN_NOTIFICATION;
184 cmd.cmd.therm.hw_slct_notification.request =
185 NV_RM_PMU_THERM_HW_SLOWDOWN_NOTIFICATION_REQUEST_ENABLE;
186
187 return therm_pmu_cmd_post(g, &cmd, NULL, NULL,
188 PMU_COMMAND_QUEUE_LPQ,
189 NULL,
190 NULL,
191 &seqdesc, ~0);
192}
193
194static u32 therm_send_slct_configuration_to_pmu(struct gk20a *g)
195{
196 u32 seqdesc = 0;
197 struct pmu_cmd cmd;
198 struct pmu_msg msg;
199 struct pmu_payload payload;
200 struct nv_pmu_therm_rpc rpccall;
201 struct therm_pmucmdhandler_params handlerparams;
202
203 memset(&payload, 0, sizeof(struct pmu_payload));
204 memset(&cmd, 0, sizeof(struct pmu_cmd));
205 memset(&msg, 0, sizeof(struct pmu_msg));
206 memset(&rpccall, 0, sizeof(struct nv_pmu_therm_rpc));
207 memset(&handlerparams, 0, sizeof(struct therm_pmucmdhandler_params));
208
209 rpccall.function = NV_PMU_THERM_RPC_ID_SLCT;
210 rpccall.params.slct.mask_enabled =
211 (1 << NV_PMU_THERM_EVENT_THERMAL_1);
212 rpccall.b_supported = 0;
213
214 cmd.hdr.unit_id = PMU_UNIT_THERM;
215 cmd.hdr.size = ((u32)sizeof(struct nv_pmu_therm_cmd_rpc) +
216 (u32)sizeof(struct pmu_hdr));
217 cmd.cmd.therm.cmd_type = NV_PMU_THERM_CMD_ID_RPC;
218
219 msg.hdr.size = sizeof(struct pmu_msg);
220
221 payload.in.buf = (u8 *)&rpccall;
222 payload.in.size = (u32)sizeof(struct nv_pmu_therm_rpc);
223 payload.in.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED;
224 payload.in.offset = NV_PMU_THERM_CMD_RPC_ALLOC_OFFSET;
225
226 payload.out.buf = (u8 *)&rpccall;
227 payload.out.size = (u32)sizeof(struct nv_pmu_therm_rpc);
228 payload.out.fb_size = PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED;
229 payload.out.offset = NV_PMU_CLK_MSG_RPC_ALLOC_OFFSET;
230
231 /* Setup the handler params to communicate back results.*/
232 handlerparams.success = 0;
233 handlerparams.prpccall = &rpccall;
234
235 return therm_pmu_cmd_post(g, &cmd, NULL, &payload,
236 PMU_COMMAND_QUEUE_LPQ,
237 therm_pmucmdhandler,
238 (void *)&handlerparams,
239 &seqdesc, ~0);
240}
241
242u32 therm_configure_therm_alert(struct gk20a *g)
243{
244 u32 status;
245
246 status = therm_enable_slct_notification_request(g);
247 if (status) {
248 nvgpu_err(g,
249 "therm_enable_slct_notification_request-failed %d",
250 status);
251 goto exit;
252 }
253
254 status = therm_send_slct_configuration_to_pmu(g);
255 if (status) {
256 nvgpu_err(g,
257 "therm_send_slct_configuration_to_pmu-failed %d",
258 status);
259 goto exit;
260 }
261
262 status = therm_set_warn_temp_limit(g);
263 if (status) {
264 nvgpu_err(g,
265 "therm_set_warn_temp_limit-failed %d",
266 status);
267 goto exit;
268 }
269exit:
270 return status;
271}