From 4c074ba3021e7fd52b10a5e7267b36e07da5660a Mon Sep 17 00:00:00 2001 From: Vijayakumar Date: Mon, 25 May 2015 15:01:04 +0530 Subject: gpu: nvgpu: gp10b: dma support for secure gpccs bug 200080684 Change-Id: I013a0ca7762f6cca0498bd282303597bf683cb7d Signed-off-by: Vijayakumar Reviewed-on: http://git-master/r/746737 Reviewed-by: Terje Bergstrom Tested-by: Terje Bergstrom --- drivers/gpu/nvgpu/gp10b/pmu_gp10b.c | 74 +++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) (limited to 'drivers/gpu/nvgpu/gp10b/pmu_gp10b.c') diff --git a/drivers/gpu/nvgpu/gp10b/pmu_gp10b.c b/drivers/gpu/nvgpu/gp10b/pmu_gp10b.c index b8b985b3..7b806026 100644 --- a/drivers/gpu/nvgpu/gp10b/pmu_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/pmu_gp10b.c @@ -21,6 +21,8 @@ #include "pmu_gp10b.h" +#define gp10b_dbg_pmu(fmt, arg...) \ + gk20a_dbg(gpu_dbg_pmu, fmt, ##arg) /*! * Structure/object which single register write need to be done during PG init * sequence to set PROD values. @@ -130,6 +132,76 @@ static struct pg_init_sequence_list _pginitseq_gp10b[] = { {0x0010e004, 0x0000008E}, }; +void gp10b_pmu_load_multiple_falcons(struct gk20a *g, u32 falconidmask, + u32 flags) +{ + struct pmu_gk20a *pmu = &g->pmu; + struct pmu_cmd cmd; + u32 seq; + + gk20a_dbg_fn(""); + + gp10b_dbg_pmu("wprinit status = %x\n", g->ops.pmu.lspmuwprinitdone); + if (g->ops.pmu.lspmuwprinitdone) { + /* send message to load FECS falcon */ + memset(&cmd, 0, sizeof(struct pmu_cmd)); + cmd.hdr.unit_id = PMU_UNIT_ACR; + cmd.hdr.size = PMU_CMD_HDR_SIZE + + sizeof(struct pmu_acr_cmd_bootstrap_multiple_falcons); + cmd.cmd.acr.boot_falcons.cmd_type = + PMU_ACR_CMD_ID_BOOTSTRAP_MULTIPLE_FALCONS; + cmd.cmd.acr.boot_falcons.flags = flags; + cmd.cmd.acr.boot_falcons.falconidmask = + falconidmask; + cmd.cmd.acr.boot_falcons.usevamask = + 1 << LSF_FALCON_ID_GPCCS; + cmd.cmd.acr.boot_falcons.wprvirtualbase.lo = + u64_lo32(g->pmu.wpr_buf.gpu_va); + cmd.cmd.acr.boot_falcons.wprvirtualbase.hi = + u64_hi32(g->pmu.wpr_buf.gpu_va); + gp10b_dbg_pmu("PMU_ACR_CMD_ID_BOOTSTRAP_MULTIPLE_FALCONS:%x\n", + falconidmask); + gk20a_pmu_cmd_post(g, &cmd, NULL, NULL, PMU_COMMAND_QUEUE_HPQ, + pmu_handle_fecs_boot_acr_msg, pmu, &seq, ~0); + } + + gk20a_dbg_fn("done"); + return; +} + +int gp10b_load_falcon_ucode(struct gk20a *g, u32 falconidmask) +{ + u32 flags = PMU_ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES; + + /* GM20B PMU supports loading FECS and GPCCS only */ + if (falconidmask == 0) + return -EINVAL; + if (falconidmask & ~((1 << LSF_FALCON_ID_FECS) | + (1 << LSF_FALCON_ID_GPCCS))) + return -EINVAL; + g->ops.pmu.lsfloadedfalconid = 0; + /* check whether pmu is ready to bootstrap lsf if not wait for it */ + if (!g->ops.pmu.lspmuwprinitdone) { + pmu_wait_message_cond(&g->pmu, + gk20a_get_gr_idle_timeout(g), + &g->ops.pmu.lspmuwprinitdone, 1); + /* check again if it still not ready indicate an error */ + if (!g->ops.pmu.lspmuwprinitdone) { + gk20a_err(dev_from_gk20a(g), + "PMU not ready to load LSF"); + return -ETIMEDOUT; + } + } + /* load falcon(s) */ + gp10b_pmu_load_multiple_falcons(g, falconidmask, flags); + pmu_wait_message_cond(&g->pmu, + gk20a_get_gr_idle_timeout(g), + &g->ops.pmu.lsfloadedfalconid, falconidmask); + if (g->ops.pmu.lsfloadedfalconid != falconidmask) + return -ETIMEDOUT; + return 0; +} + static int gp10b_pmu_setup_elpg(struct gk20a *g) { int ret = 0; @@ -157,8 +229,10 @@ void gp10b_init_pmu_ops(struct gpu_ops *gops) if (gops->privsecurity) { gm20b_init_secure_pmu(gops); gops->pmu.init_wpr_region = gm20b_pmu_init_acr; + gops->pmu.load_lsfalcon_ucode = gp10b_load_falcon_ucode; } else { gk20a_init_pmu_ops(gops); + gops->pmu.load_lsfalcon_ucode = NULL; gops->pmu.init_wpr_region = NULL; } gops->pmu.pmu_setup_elpg = gp10b_pmu_setup_elpg; -- cgit v1.2.2