summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/therm/thrmpmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/therm/thrmpmu.c')
-rw-r--r--drivers/gpu/nvgpu/therm/thrmpmu.c270
1 files changed, 270 insertions, 0 deletions
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}