diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/pmu_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 118 |
1 files changed, 33 insertions, 85 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c index 2f8e456f..fefa77fc 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | |||
@@ -200,38 +200,11 @@ void pmu_copy_to_dmem(struct nvgpu_pmu *pmu, | |||
200 | return; | 200 | return; |
201 | } | 201 | } |
202 | 202 | ||
203 | int pmu_idle(struct nvgpu_pmu *pmu) | ||
204 | { | ||
205 | struct gk20a *g = gk20a_from_pmu(pmu); | ||
206 | struct nvgpu_timeout timeout; | ||
207 | u32 idle_stat; | ||
208 | |||
209 | nvgpu_timeout_init(g, &timeout, 2000, NVGPU_TIMER_RETRY_TIMER); | ||
210 | |||
211 | /* wait for pmu idle */ | ||
212 | do { | ||
213 | idle_stat = gk20a_readl(g, pwr_falcon_idlestate_r()); | ||
214 | |||
215 | if (pwr_falcon_idlestate_falcon_busy_v(idle_stat) == 0 && | ||
216 | pwr_falcon_idlestate_ext_busy_v(idle_stat) == 0) { | ||
217 | break; | ||
218 | } | ||
219 | |||
220 | if (nvgpu_timeout_expired_msg(&timeout, | ||
221 | "waiting for pmu idle: 0x%08x", | ||
222 | idle_stat)) | ||
223 | return -EBUSY; | ||
224 | |||
225 | nvgpu_usleep_range(100, 200); | ||
226 | } while (1); | ||
227 | |||
228 | gk20a_dbg_fn("done"); | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | void pmu_enable_irq(struct nvgpu_pmu *pmu, bool enable) | 203 | void pmu_enable_irq(struct nvgpu_pmu *pmu, bool enable) |
233 | { | 204 | { |
234 | struct gk20a *g = gk20a_from_pmu(pmu); | 205 | struct gk20a *g = gk20a_from_pmu(pmu); |
206 | u32 intr_mask; | ||
207 | u32 intr_dest; | ||
235 | 208 | ||
236 | gk20a_dbg_fn(""); | 209 | gk20a_dbg_fn(""); |
237 | 210 | ||
@@ -240,21 +213,11 @@ void pmu_enable_irq(struct nvgpu_pmu *pmu, bool enable) | |||
240 | g->ops.mc.intr_unit_config(g, MC_INTR_UNIT_DISABLE, false, | 213 | g->ops.mc.intr_unit_config(g, MC_INTR_UNIT_DISABLE, false, |
241 | mc_intr_mask_1_pmu_enabled_f()); | 214 | mc_intr_mask_1_pmu_enabled_f()); |
242 | 215 | ||
243 | gk20a_writel(g, pwr_falcon_irqmclr_r(), | 216 | nvgpu_flcn_set_irq(pmu->flcn, false, 0x0, 0x0); |
244 | pwr_falcon_irqmclr_gptmr_f(1) | | ||
245 | pwr_falcon_irqmclr_wdtmr_f(1) | | ||
246 | pwr_falcon_irqmclr_mthd_f(1) | | ||
247 | pwr_falcon_irqmclr_ctxsw_f(1) | | ||
248 | pwr_falcon_irqmclr_halt_f(1) | | ||
249 | pwr_falcon_irqmclr_exterr_f(1) | | ||
250 | pwr_falcon_irqmclr_swgen0_f(1) | | ||
251 | pwr_falcon_irqmclr_swgen1_f(1) | | ||
252 | pwr_falcon_irqmclr_ext_f(0xff)); | ||
253 | 217 | ||
254 | if (enable) { | 218 | if (enable) { |
255 | /* dest 0=falcon, 1=host; level 0=irq0, 1=irq1 */ | 219 | /* dest 0=falcon, 1=host; level 0=irq0, 1=irq1 */ |
256 | gk20a_writel(g, pwr_falcon_irqdest_r(), | 220 | intr_dest = pwr_falcon_irqdest_host_gptmr_f(0) | |
257 | pwr_falcon_irqdest_host_gptmr_f(0) | | ||
258 | pwr_falcon_irqdest_host_wdtmr_f(1) | | 221 | pwr_falcon_irqdest_host_wdtmr_f(1) | |
259 | pwr_falcon_irqdest_host_mthd_f(0) | | 222 | pwr_falcon_irqdest_host_mthd_f(0) | |
260 | pwr_falcon_irqdest_host_ctxsw_f(0) | | 223 | pwr_falcon_irqdest_host_ctxsw_f(0) | |
@@ -271,18 +234,19 @@ void pmu_enable_irq(struct nvgpu_pmu *pmu, bool enable) | |||
271 | pwr_falcon_irqdest_target_exterr_f(0) | | 234 | pwr_falcon_irqdest_target_exterr_f(0) | |
272 | pwr_falcon_irqdest_target_swgen0_f(0) | | 235 | pwr_falcon_irqdest_target_swgen0_f(0) | |
273 | pwr_falcon_irqdest_target_swgen1_f(0) | | 236 | pwr_falcon_irqdest_target_swgen1_f(0) | |
274 | pwr_falcon_irqdest_target_ext_f(0xff)); | 237 | pwr_falcon_irqdest_target_ext_f(0xff); |
275 | 238 | ||
276 | /* 0=disable, 1=enable */ | 239 | /* 0=disable, 1=enable */ |
277 | gk20a_writel(g, pwr_falcon_irqmset_r(), | 240 | intr_mask = pwr_falcon_irqmset_gptmr_f(1) | |
278 | pwr_falcon_irqmset_gptmr_f(1) | | ||
279 | pwr_falcon_irqmset_wdtmr_f(1) | | 241 | pwr_falcon_irqmset_wdtmr_f(1) | |
280 | pwr_falcon_irqmset_mthd_f(0) | | 242 | pwr_falcon_irqmset_mthd_f(0) | |
281 | pwr_falcon_irqmset_ctxsw_f(0) | | 243 | pwr_falcon_irqmset_ctxsw_f(0) | |
282 | pwr_falcon_irqmset_halt_f(1) | | 244 | pwr_falcon_irqmset_halt_f(1) | |
283 | pwr_falcon_irqmset_exterr_f(1) | | 245 | pwr_falcon_irqmset_exterr_f(1) | |
284 | pwr_falcon_irqmset_swgen0_f(1) | | 246 | pwr_falcon_irqmset_swgen0_f(1) | |
285 | pwr_falcon_irqmset_swgen1_f(1)); | 247 | pwr_falcon_irqmset_swgen1_f(1); |
248 | |||
249 | nvgpu_flcn_set_irq(pmu->flcn, true, intr_mask, intr_dest); | ||
286 | 250 | ||
287 | g->ops.mc.intr_unit_config(g, MC_INTR_UNIT_ENABLE, true, | 251 | g->ops.mc.intr_unit_config(g, MC_INTR_UNIT_ENABLE, true, |
288 | mc_intr_mask_0_pmu_enabled_f()); | 252 | mc_intr_mask_0_pmu_enabled_f()); |
@@ -295,6 +259,7 @@ int pmu_enable_hw(struct nvgpu_pmu *pmu, bool enable) | |||
295 | { | 259 | { |
296 | struct gk20a *g = gk20a_from_pmu(pmu); | 260 | struct gk20a *g = gk20a_from_pmu(pmu); |
297 | struct nvgpu_timeout timeout; | 261 | struct nvgpu_timeout timeout; |
262 | int err = 0; | ||
298 | 263 | ||
299 | gk20a_dbg_fn(""); | 264 | gk20a_dbg_fn(""); |
300 | 265 | ||
@@ -313,13 +278,9 @@ int pmu_enable_hw(struct nvgpu_pmu *pmu, bool enable) | |||
313 | PMU_MEM_SCRUBBING_TIMEOUT_DEFAULT, | 278 | PMU_MEM_SCRUBBING_TIMEOUT_DEFAULT, |
314 | NVGPU_TIMER_RETRY_TIMER); | 279 | NVGPU_TIMER_RETRY_TIMER); |
315 | do { | 280 | do { |
316 | u32 w = gk20a_readl(g, pwr_falcon_dmactl_r()) & | 281 | if (nvgpu_flcn_get_mem_scrubbing_status(pmu->flcn)) { |
317 | (pwr_falcon_dmactl_dmem_scrubbing_m() | | ||
318 | pwr_falcon_dmactl_imem_scrubbing_m()); | ||
319 | |||
320 | if (!w) { | ||
321 | gk20a_dbg_fn("done"); | 282 | gk20a_dbg_fn("done"); |
322 | return 0; | 283 | goto exit; |
323 | } | 284 | } |
324 | nvgpu_udelay(PMU_MEM_SCRUBBING_TIMEOUT_DEFAULT); | 285 | nvgpu_udelay(PMU_MEM_SCRUBBING_TIMEOUT_DEFAULT); |
325 | } while (!nvgpu_timeout_expired(&timeout)); | 286 | } while (!nvgpu_timeout_expired(&timeout)); |
@@ -327,11 +288,12 @@ int pmu_enable_hw(struct nvgpu_pmu *pmu, bool enable) | |||
327 | g->ops.mc.disable(g, mc_enable_pwr_enabled_f()); | 288 | g->ops.mc.disable(g, mc_enable_pwr_enabled_f()); |
328 | nvgpu_err(g, "Falcon mem scrubbing timeout"); | 289 | nvgpu_err(g, "Falcon mem scrubbing timeout"); |
329 | 290 | ||
330 | return -ETIMEDOUT; | 291 | err = -ETIMEDOUT; |
331 | } else { | 292 | } else |
332 | g->ops.mc.disable(g, mc_enable_pwr_enabled_f()); | 293 | g->ops.mc.disable(g, mc_enable_pwr_enabled_f()); |
333 | return 0; | 294 | |
334 | } | 295 | exit: |
296 | return err; | ||
335 | } | 297 | } |
336 | 298 | ||
337 | static int pmu_enable(struct nvgpu_pmu *pmu, bool enable) | 299 | static int pmu_enable(struct nvgpu_pmu *pmu, bool enable) |
@@ -357,7 +319,7 @@ static int pmu_enable(struct nvgpu_pmu *pmu, bool enable) | |||
357 | 319 | ||
358 | /* TBD: post reset */ | 320 | /* TBD: post reset */ |
359 | 321 | ||
360 | err = pmu_idle(pmu); | 322 | err = nvgpu_flcn_wait_idle(pmu->flcn); |
361 | if (err) | 323 | if (err) |
362 | return err; | 324 | return err; |
363 | 325 | ||
@@ -368,31 +330,6 @@ static int pmu_enable(struct nvgpu_pmu *pmu, bool enable) | |||
368 | return 0; | 330 | return 0; |
369 | } | 331 | } |
370 | 332 | ||
371 | int pmu_reset(struct nvgpu_pmu *pmu) | ||
372 | { | ||
373 | int err; | ||
374 | |||
375 | err = pmu_idle(pmu); | ||
376 | if (err) | ||
377 | return err; | ||
378 | |||
379 | /* TBD: release pmu hw mutex */ | ||
380 | |||
381 | err = pmu_enable(pmu, false); | ||
382 | if (err) | ||
383 | return err; | ||
384 | |||
385 | /* TBD: cancel all sequences */ | ||
386 | /* TBD: init all sequences and state tables */ | ||
387 | /* TBD: restore pre-init message handler */ | ||
388 | |||
389 | err = pmu_enable(pmu, true); | ||
390 | if (err) | ||
391 | return err; | ||
392 | |||
393 | return 0; | ||
394 | } | ||
395 | |||
396 | int pmu_bootstrap(struct nvgpu_pmu *pmu) | 333 | int pmu_bootstrap(struct nvgpu_pmu *pmu) |
397 | { | 334 | { |
398 | struct gk20a *g = gk20a_from_pmu(pmu); | 335 | struct gk20a *g = gk20a_from_pmu(pmu); |
@@ -704,7 +641,7 @@ static int gk20a_init_pmu_setup_hw1(struct gk20a *g) | |||
704 | gk20a_dbg_fn(""); | 641 | gk20a_dbg_fn(""); |
705 | 642 | ||
706 | nvgpu_mutex_acquire(&pmu->isr_mutex); | 643 | nvgpu_mutex_acquire(&pmu->isr_mutex); |
707 | g->ops.pmu.reset(g); | 644 | nvgpu_flcn_reset(pmu->flcn); |
708 | pmu->isr_enabled = true; | 645 | pmu->isr_enabled = true; |
709 | nvgpu_mutex_release(&pmu->isr_mutex); | 646 | nvgpu_mutex_release(&pmu->isr_mutex); |
710 | 647 | ||
@@ -737,11 +674,22 @@ static void gk20a_write_dmatrfbase(struct gk20a *g, u32 addr) | |||
737 | 674 | ||
738 | int gk20a_pmu_reset(struct gk20a *g) | 675 | int gk20a_pmu_reset(struct gk20a *g) |
739 | { | 676 | { |
740 | int err; | ||
741 | struct nvgpu_pmu *pmu = &g->pmu; | 677 | struct nvgpu_pmu *pmu = &g->pmu; |
678 | int err; | ||
679 | |||
680 | err = nvgpu_flcn_wait_idle(pmu->flcn); | ||
681 | if (err) | ||
682 | goto exit; | ||
683 | |||
684 | err = pmu_enable(pmu, false); | ||
685 | if (err) | ||
686 | goto exit; | ||
742 | 687 | ||
743 | err = pmu_reset(pmu); | 688 | err = pmu_enable(pmu, true); |
689 | if (err) | ||
690 | goto exit; | ||
744 | 691 | ||
692 | exit: | ||
745 | return err; | 693 | return err; |
746 | } | 694 | } |
747 | 695 | ||
@@ -799,7 +747,7 @@ void gk20a_init_pmu_ops(struct gpu_ops *gops) | |||
799 | gops->pmu.alloc_blob_space = NULL; | 747 | gops->pmu.alloc_blob_space = NULL; |
800 | gops->pmu.pmu_populate_loader_cfg = NULL; | 748 | gops->pmu.pmu_populate_loader_cfg = NULL; |
801 | gops->pmu.flcn_populate_bl_dmem_desc = NULL; | 749 | gops->pmu.flcn_populate_bl_dmem_desc = NULL; |
802 | gops->pmu.reset = gk20a_pmu_reset; | 750 | gops->pmu.reset = NULL; |
803 | } | 751 | } |
804 | 752 | ||
805 | static void pmu_handle_zbc_msg(struct gk20a *g, struct pmu_msg *msg, | 753 | static void pmu_handle_zbc_msg(struct gk20a *g, struct pmu_msg *msg, |