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/gr_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/gr_gm20b.c')
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/gr_gm20b.c | 69 |
1 files changed, 63 insertions, 6 deletions
diff --git a/drivers/gpu/nvgpu/gm20b/gr_gm20b.c b/drivers/gpu/nvgpu/gm20b/gr_gm20b.c index 660ffa88..8a3de4e8 100644 --- a/drivers/gpu/nvgpu/gm20b/gr_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/gr_gm20b.c | |||
@@ -14,6 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | #include <linux/delay.h> /* for mdelay */ | ||
17 | 18 | ||
18 | #include "gk20a/gk20a.h" | 19 | #include "gk20a/gk20a.h" |
19 | #include "gk20a/gr_gk20a.h" | 20 | #include "gk20a/gr_gk20a.h" |
@@ -24,6 +25,8 @@ | |||
24 | #include "hw_proj_gm20b.h" | 25 | #include "hw_proj_gm20b.h" |
25 | #include "hw_ctxsw_prog_gm20b.h" | 26 | #include "hw_ctxsw_prog_gm20b.h" |
26 | #include "hw_fuse_gm20b.h" | 27 | #include "hw_fuse_gm20b.h" |
28 | #include "pmu_gm20b.h" | ||
29 | #include "acr_gm20b.h" | ||
27 | 30 | ||
28 | static void gr_gm20b_init_gpc_mmu(struct gk20a *g) | 31 | static void gr_gm20b_init_gpc_mmu(struct gk20a *g) |
29 | { | 32 | { |
@@ -625,8 +628,29 @@ static void gr_gm20b_load_gpccs_with_bootloader(struct gk20a *g) | |||
625 | gr_fecs_falcon_hwcfg_r()); | 628 | gr_fecs_falcon_hwcfg_r()); |
626 | } | 629 | } |
627 | 630 | ||
631 | static int gr_gm20b_ctx_wait_lsf_ready(struct gk20a *g, u32 timeout, u32 val) | ||
632 | { | ||
633 | unsigned long end_jiffies = jiffies + msecs_to_jiffies(timeout); | ||
634 | unsigned long delay = GR_IDLE_CHECK_DEFAULT; | ||
635 | u32 reg; | ||
636 | |||
637 | gk20a_dbg_fn(""); | ||
638 | reg = gk20a_readl(g, gr_fecs_ctxsw_mailbox_r(0)); | ||
639 | do { | ||
640 | reg = gk20a_readl(g, gr_fecs_ctxsw_mailbox_r(0)); | ||
641 | if (reg == val) | ||
642 | return 0; | ||
643 | usleep_range(delay, delay * 2); | ||
644 | delay = min_t(u32, delay << 1, GR_IDLE_CHECK_MAX); | ||
645 | } while (time_before(jiffies, end_jiffies) || | ||
646 | !tegra_platform_is_silicon()); | ||
647 | |||
648 | return -ETIMEDOUT; | ||
649 | } | ||
650 | |||
628 | static int gr_gm20b_load_ctxsw_ucode(struct gk20a *g) | 651 | static int gr_gm20b_load_ctxsw_ucode(struct gk20a *g) |
629 | { | 652 | { |
653 | u32 err; | ||
630 | gk20a_dbg_fn(""); | 654 | gk20a_dbg_fn(""); |
631 | 655 | ||
632 | if (tegra_platform_is_linsim()) { | 656 | if (tegra_platform_is_linsim()) { |
@@ -636,16 +660,49 @@ static int gr_gm20b_load_ctxsw_ucode(struct gk20a *g) | |||
636 | gr_gpccs_ctxsw_mailbox_value_f(0xc0de7777)); | 660 | gr_gpccs_ctxsw_mailbox_value_f(0xc0de7777)); |
637 | } | 661 | } |
638 | 662 | ||
663 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(0), ~0x0); | ||
664 | gm20b_pmu_load_lsf(g, LSF_FALCON_ID_FECS); | ||
665 | |||
639 | gr_gm20b_load_gpccs_with_bootloader(g); | 666 | gr_gm20b_load_gpccs_with_bootloader(g); |
640 | 667 | ||
641 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(0), 0x0); | 668 | if (g->ops.pmu.fecsrecoveryinprogress) { |
642 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_r(1), 0x1); | 669 | unsigned long timeout = gk20a_get_gr_idle_timeout(g); |
643 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(6), 0xffffffff); | 670 | err = gr_gm20b_ctx_wait_lsf_ready(g, timeout, 0x55AA55AA); |
671 | if (err) { | ||
672 | gk20a_err(dev_from_gk20a(g), "Unable to recover FECS"); | ||
673 | return err; | ||
674 | } else { | ||
675 | g->ops.pmu.fecsrecoveryinprogress = 0; | ||
676 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(0), ~0x0); | ||
677 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_r(1), 0x1); | ||
678 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(6), | ||
679 | 0xffffffff); | ||
680 | |||
681 | gk20a_writel(g, gr_gpccs_dmactl_r(), | ||
682 | gr_gpccs_dmactl_require_ctx_f(0)); | ||
683 | gk20a_writel(g, gr_gpccs_cpuctl_r(), | ||
684 | gr_gpccs_cpuctl_startcpu_f(1)); | ||
685 | |||
686 | gk20a_writel(g, gr_fecs_cpuctl_alias_r(), | ||
687 | gr_fecs_cpuctl_startcpu_f(1)); | ||
688 | } | ||
689 | } | ||
644 | 690 | ||
645 | gk20a_writel(g, gr_gpccs_dmactl_r(), gr_gpccs_dmactl_require_ctx_f(0)); | ||
646 | 691 | ||
647 | gk20a_writel(g, gr_gpccs_cpuctl_r(), gr_gpccs_cpuctl_startcpu_f(1)); | 692 | if (!g->ops.pmu.fecsbootstrapdone) { |
648 | gk20a_writel(g, gr_fecs_cpuctl_alias_r(), gr_fecs_cpuctl_startcpu_f(1)); | 693 | g->ops.pmu.fecsbootstrapdone = true; |
694 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(0), ~0x0); | ||
695 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_r(1), 0x1); | ||
696 | gk20a_writel(g, gr_fecs_ctxsw_mailbox_clear_r(6), 0xffffffff); | ||
697 | |||
698 | gk20a_writel(g, gr_gpccs_dmactl_r(), | ||
699 | gr_gpccs_dmactl_require_ctx_f(0)); | ||
700 | gk20a_writel(g, gr_gpccs_cpuctl_r(), | ||
701 | gr_gpccs_cpuctl_startcpu_f(1)); | ||
702 | |||
703 | gk20a_writel(g, gr_fecs_cpuctl_alias_r(), | ||
704 | gr_fecs_cpuctl_startcpu_f(1)); | ||
705 | } | ||
649 | 706 | ||
650 | gk20a_dbg_fn("done"); | 707 | gk20a_dbg_fn("done"); |
651 | 708 | ||