From be04b9b1b56d6dd478fe521277c079367c03f39d Mon Sep 17 00:00:00 2001 From: Mahantesh Kumbar Date: Tue, 25 Apr 2017 12:22:56 +0530 Subject: gpu: nvgpu: falcon reset support - Added flacon reset dependent interface & HAL methods to perform falcon reset. - method to wait for idle - method to reset falcon - method to set irq - method to read status of CPU - Updated falcon ops pointer to point gk20a falcon HAL methods - Added members to know support of falcon & interrupt. - Added falcon dependency ops member to support flacon speicifc methods JIRA NVGPU-99 JIRA NVGPU-101 Change-Id: I411477e5696a61ee73caebfdab625763b522c255 Signed-off-by: Mahantesh Kumbar Reviewed-on: http://git-master/r/1469453 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Vijayakumar Subbu --- drivers/gpu/nvgpu/gk20a/flcn_gk20a.c | 137 +++++++++++++++++++++++++++++------ 1 file changed, 113 insertions(+), 24 deletions(-) (limited to 'drivers/gpu/nvgpu/gk20a') diff --git a/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c b/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c index f36b9e32..9568b979 100644 --- a/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c @@ -10,56 +10,145 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. */ +#include + #include "gk20a/gk20a.h" +#include + +static int gk20a_flcn_reset(struct nvgpu_falcon *flcn) +{ + struct gk20a *g = flcn->g; + u32 base_addr = flcn->flcn_base; + u32 unit_status = 0; + int status = 0; + + if (flcn->flcn_engine_dep_ops.reset_eng) + /* falcon & engine reset */ + status = flcn->flcn_engine_dep_ops.reset_eng(g); + else { + /* do falcon CPU hard reset */ + unit_status = gk20a_readl(g, base_addr + + falcon_falcon_cpuctl_r()); + gk20a_writel(g, base_addr + falcon_falcon_cpuctl_r(), + (unit_status | falcon_falcon_cpuctl_hreset_f(1))); + } + + return status; +} + +static void gk20a_flcn_set_irq(struct nvgpu_falcon *flcn, bool enable) +{ + struct gk20a *g = flcn->g; + u32 base_addr = flcn->flcn_base; + + if (!flcn->is_interrupt_enabled) { + nvgpu_warn(g, "Interrupt not supported on flcn 0x%x ", + flcn->flcn_id); + /* Keep interrupt disabled */ + enable = false; + } + + if (enable) { + gk20a_writel(g, base_addr + falcon_falcon_irqmset_r(), + flcn->intr_mask); + gk20a_writel(g, base_addr + falcon_falcon_irqdest_r(), + flcn->intr_dest); + } else + gk20a_writel(g, base_addr + falcon_falcon_irqmclr_r(), + 0xffffffff); +} + +static bool gk20a_is_falcon_cpu_halted(struct nvgpu_falcon *flcn) +{ + struct gk20a *g = flcn->g; + u32 base_addr = flcn->flcn_base; + + return (gk20a_readl(g, base_addr + falcon_falcon_cpuctl_r()) & + falcon_falcon_cpuctl_halt_intr_m() ? + true : false); +} + +static bool gk20a_is_falcon_idle(struct nvgpu_falcon *flcn) +{ + struct gk20a *g = flcn->g; + u32 base_addr = flcn->flcn_base; + u32 unit_status = 0; + bool status = false; + + unit_status = gk20a_readl(g, + base_addr + falcon_falcon_idlestate_r()); + + if (falcon_falcon_idlestate_falcon_busy_v(unit_status) == 0 && + falcon_falcon_idlestate_ext_busy_v(unit_status) == 0) + status = true; + else + status = false; + + return status; +} + +static bool gk20a_is_falcon_scrubbing_done(struct nvgpu_falcon *flcn) +{ + struct gk20a *g = flcn->g; + u32 base_addr = flcn->flcn_base; + u32 unit_status = 0; + bool status = false; + + unit_status = gk20a_readl(g, + base_addr + falcon_falcon_dmactl_r()); + + if (unit_status & (falcon_falcon_dmactl_dmem_scrubbing_m() | + falcon_falcon_dmactl_imem_scrubbing_m())) + status = false; + else + status = true; + + return status; +} + static void gk20a_falcon_ops(struct nvgpu_falcon *flcn) { struct nvgpu_falcon_ops *flcn_ops = &flcn->flcn_ops; - struct nvgpu_falcon_version_ops *flcn_vops = &flcn->flcn_vops; - - flcn_ops->reset = NULL; - flcn_ops->enable_irq = NULL; - flcn_ops->fbif_transcfg = NULL; - flcn_ops->read_hwcfg = NULL; - flcn_ops->write_hwcfg = NULL; - flcn_ops->copy_from_dmem = NULL; - flcn_ops->copy_to_dmem = NULL; - flcn_ops->dma_copy = NULL; - flcn_ops->mailbox_read = NULL; - flcn_ops->mailbox_write = NULL; - flcn_ops->get_unit_status = NULL; - flcn_ops->dump_falcon_stats = NULL; - - flcn_vops->start_cpu_secure = NULL; - flcn_vops->write_dmatrfbase = NULL; + + flcn_ops->reset = gk20a_flcn_reset; + flcn_ops->set_irq = gk20a_flcn_set_irq; + flcn_ops->is_falcon_cpu_halted = gk20a_is_falcon_cpu_halted; + flcn_ops->is_falcon_idle = gk20a_is_falcon_idle; + flcn_ops->is_falcon_scrubbing_done = gk20a_is_falcon_scrubbing_done; } static void gk20a_falcon_hal_sw_init(struct nvgpu_falcon *flcn) { struct gk20a *g = flcn->g; - switch (flcn->flcn_id) { case FALCON_ID_PMU: flcn->flcn_base = FALCON_PWR_BASE; + flcn->is_falcon_supported = true; + flcn->is_interrupt_enabled = true; break; - case FALCON_ID_SEC2: - flcn->flcn_base = FALCON_SEC_BASE; - break; case FALCON_ID_FECS: flcn->flcn_base = FALCON_FECS_BASE; + flcn->is_falcon_supported = true; + flcn->is_interrupt_enabled = false; break; case FALCON_ID_GPCCS: flcn->flcn_base = FALCON_GPCCS_BASE; + flcn->is_falcon_supported = true; + flcn->is_interrupt_enabled = false; break; default: + flcn->is_falcon_supported = false; nvgpu_err(g, "Invalid flcn request"); break; } - nvgpu_mutex_init(&flcn->copy_lock); - - gk20a_falcon_ops(flcn); + if (flcn->is_falcon_supported) { + gk20a_falcon_ops(flcn); + } else + nvgpu_info(g, "flcn-Id 0x%x not supported on current chip", + flcn->flcn_id); } void gk20a_falcon_init_hal(struct gpu_ops *gops) -- cgit v1.2.2