diff options
author | Vijayakumar <vsubbu@nvidia.com> | 2014-09-30 10:49:44 -0400 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2015-03-18 15:11:52 -0400 |
commit | 748475df20bbe6843bdf4fbc02384dc5aa28866e (patch) | |
tree | 700012cf758d6731017b8b23153abae4311bf065 /drivers/gpu/nvgpu/gm20b/pmu_gm20b.c | |
parent | 4739499f07b29282ee1031d08adaa76c238da2a6 (diff) |
gpu: nvgpu: gm20b: Support secure FECS recovery
When falcons are secured use PMU commands to reload
FECS firmware.
Bug 200042729
Change-Id: I09f2472b16dac6a510dba067bce3950075973d5f
Signed-off-by: Vijayakumar <vsubbu@nvidia.com>
Reviewed-on: http://git-master/r/552544
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gm20b/pmu_gm20b.c')
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/pmu_gm20b.c | 96 |
1 files changed, 94 insertions, 2 deletions
diff --git a/drivers/gpu/nvgpu/gm20b/pmu_gm20b.c b/drivers/gpu/nvgpu/gm20b/pmu_gm20b.c index 98dc6845..91927950 100644 --- a/drivers/gpu/nvgpu/gm20b/pmu_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/pmu_gm20b.c | |||
@@ -13,7 +13,9 @@ | |||
13 | * more details. | 13 | * more details. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/delay.h> /* for udelay */ | ||
16 | #include "gk20a/gk20a.h" | 17 | #include "gk20a/gk20a.h" |
18 | #include "gk20a/pmu_gk20a.h" | ||
17 | #include "acr_gm20b.h" | 19 | #include "acr_gm20b.h" |
18 | #include "pmu_gm20b.h" | 20 | #include "pmu_gm20b.h" |
19 | 21 | ||
@@ -26,6 +28,9 @@ struct pg_init_sequence_list { | |||
26 | u32 writeval; | 28 | u32 writeval; |
27 | }; | 29 | }; |
28 | 30 | ||
31 | #define gm20b_dbg_pmu(fmt, arg...) \ | ||
32 | gk20a_dbg(gpu_dbg_pmu, fmt, ##arg) | ||
33 | |||
29 | 34 | ||
30 | /* PROD settings for ELPG sequencing registers*/ | 35 | /* PROD settings for ELPG sequencing registers*/ |
31 | static struct pg_init_sequence_list _pginitseq_gm20b[] = { | 36 | static struct pg_init_sequence_list _pginitseq_gm20b[] = { |
@@ -148,11 +153,98 @@ int gm20b_pmu_setup_elpg(struct gk20a *g) | |||
148 | return ret; | 153 | return ret; |
149 | } | 154 | } |
150 | 155 | ||
156 | void pmu_handle_acr_init_wpr_msg(struct gk20a *g, struct pmu_msg *msg, | ||
157 | void *param, u32 handle, u32 status) | ||
158 | { | ||
159 | gk20a_dbg_fn(""); | ||
160 | |||
161 | gm20b_dbg_pmu("reply PMU_ACR_CMD_ID_INIT_WPR_REGION"); | ||
162 | |||
163 | if (msg->msg.acr.acrmsg.errorcode == PMU_ACR_SUCCESS) | ||
164 | g->ops.pmu.lspmuwprinitdone = true; | ||
165 | gk20a_dbg_fn("done"); | ||
166 | } | ||
167 | |||
168 | |||
169 | int gm20b_pmu_init_acr(struct gk20a *g) | ||
170 | { | ||
171 | struct pmu_gk20a *pmu = &g->pmu; | ||
172 | struct pmu_cmd cmd; | ||
173 | u32 seq; | ||
174 | |||
175 | gk20a_dbg_fn(""); | ||
176 | |||
177 | /* init ACR */ | ||
178 | memset(&cmd, 0, sizeof(struct pmu_cmd)); | ||
179 | cmd.hdr.unit_id = PMU_UNIT_ACR; | ||
180 | cmd.hdr.size = PMU_CMD_HDR_SIZE + | ||
181 | sizeof(struct pmu_acr_cmd_init_wpr_details); | ||
182 | cmd.cmd.acr.init_wpr.cmd_type = PMU_ACR_CMD_ID_INIT_WPR_REGION; | ||
183 | cmd.cmd.acr.init_wpr.regionid = 0x01; | ||
184 | cmd.cmd.acr.init_wpr.wproffset = 0x00; | ||
185 | gm20b_dbg_pmu("cmd post PMU_ACR_CMD_ID_INIT_WPR_REGION"); | ||
186 | gk20a_pmu_cmd_post(g, &cmd, NULL, NULL, PMU_COMMAND_QUEUE_HPQ, | ||
187 | pmu_handle_acr_init_wpr_msg, pmu, &seq, ~0); | ||
188 | |||
189 | gk20a_dbg_fn("done"); | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | void pmu_handle_fecs_boot_acr_msg(struct gk20a *g, struct pmu_msg *msg, | ||
194 | void *param, u32 handle, u32 status) | ||
195 | { | ||
196 | |||
197 | gk20a_dbg_fn(""); | ||
198 | |||
199 | |||
200 | if (msg->msg.acr.acrmsg.falconid == LSF_FALCON_ID_FECS) | ||
201 | gm20b_dbg_pmu("reply PMU_ACR_CMD_ID_BOOTSTRAP_FALCON"); | ||
202 | |||
203 | gm20b_dbg_pmu("response code = %x\n", msg->msg.acr.acrmsg.falconid); | ||
204 | gk20a_dbg_fn("done"); | ||
205 | } | ||
206 | |||
207 | void gm20b_pmu_load_lsf(struct gk20a *g, u8 falcon_id) | ||
208 | { | ||
209 | struct pmu_gk20a *pmu = &g->pmu; | ||
210 | struct pmu_cmd cmd; | ||
211 | u32 seq; | ||
212 | |||
213 | gk20a_dbg_fn(""); | ||
214 | |||
215 | gm20b_dbg_pmu("wprinit status = %x\n", g->ops.pmu.lspmuwprinitdone); | ||
216 | if (g->ops.pmu.lspmuwprinitdone && g->ops.pmu.fecsbootstrapdone) { | ||
217 | /* send message to load FECS falcon */ | ||
218 | memset(&cmd, 0, sizeof(struct pmu_cmd)); | ||
219 | cmd.hdr.unit_id = PMU_UNIT_ACR; | ||
220 | cmd.hdr.size = PMU_CMD_HDR_SIZE + | ||
221 | sizeof(struct pmu_acr_cmd_bootstrap_falcon); | ||
222 | cmd.cmd.acr.bootstrap_falcon.cmd_type = | ||
223 | PMU_ACR_CMD_ID_BOOTSTRAP_FALCON; | ||
224 | cmd.cmd.acr.bootstrap_falcon.flags = | ||
225 | PMU_ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES; | ||
226 | cmd.cmd.acr.bootstrap_falcon.falconid = falcon_id; | ||
227 | gm20b_dbg_pmu("cmd post PMU_ACR_CMD_ID_BOOTSTRAP_FALCON"); | ||
228 | g->ops.pmu.fecsrecoveryinprogress = 1; | ||
229 | gk20a_pmu_cmd_post(g, &cmd, NULL, NULL, PMU_COMMAND_QUEUE_HPQ, | ||
230 | pmu_handle_fecs_boot_acr_msg, pmu, &seq, ~0); | ||
231 | } | ||
232 | |||
233 | gk20a_dbg_fn("done"); | ||
234 | return; | ||
235 | } | ||
236 | |||
151 | void gm20b_init_pmu_ops(struct gpu_ops *gops) | 237 | void gm20b_init_pmu_ops(struct gpu_ops *gops) |
152 | { | 238 | { |
153 | if (gops->privsecurity) | 239 | if (gops->privsecurity) { |
154 | gm20b_init_secure_pmu(gops); | 240 | gm20b_init_secure_pmu(gops); |
155 | else | 241 | gops->pmu.init_wpr_region = gm20b_pmu_init_acr; |
242 | } else { | ||
156 | gk20a_init_pmu_ops(gops); | 243 | gk20a_init_pmu_ops(gops); |
244 | gops->pmu.init_wpr_region = NULL; | ||
245 | } | ||
157 | gops->pmu.pmu_setup_elpg = gm20b_pmu_setup_elpg; | 246 | gops->pmu.pmu_setup_elpg = gm20b_pmu_setup_elpg; |
247 | gops->pmu.lspmuwprinitdone = false; | ||
248 | gops->pmu.fecsbootstrapdone = false; | ||
249 | gops->pmu.fecsrecoveryinprogress = 0; | ||
158 | } | 250 | } |