From 905f1c0392bf244b321f56f82661eeb2fe00ee05 Mon Sep 17 00:00:00 2001 From: David Nieto Date: Fri, 19 Aug 2016 17:09:35 -0700 Subject: gpu: nvgpu: parse and execute mclk shadow script * Parsing of shadow registers from VBIOS * Partial devinit engine interpreter implementation JIRA DNVGPU-117 Change-Id: I42179748889f17d674ad0a986e81c418b3b8df11 Signed-off-by: David Nieto Reviewed-on: http://git-master/r/1214956 Reviewed-on: http://git-master/r/1237293 Reviewed-by: Terje Bergstrom --- drivers/gpu/nvgpu/gp106/bios_gp106.c | 121 +++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 drivers/gpu/nvgpu/gp106/bios_gp106.c (limited to 'drivers/gpu/nvgpu/gp106/bios_gp106.c') diff --git a/drivers/gpu/nvgpu/gp106/bios_gp106.c b/drivers/gpu/nvgpu/gp106/bios_gp106.c new file mode 100644 index 00000000..8be4314d --- /dev/null +++ b/drivers/gpu/nvgpu/gp106/bios_gp106.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include "gk20a/gk20a.h" +#include "gm206/bios_gm206.h" +#include "bios_gp106.h" +#include "hw_gc6_gp106.h" + +static void gp106_init_xmemsel_zm_nv_reg_array(struct gk20a *g, bool *condition, + u32 reg, u32 stride, u32 count, u32 data_table_offset) +{ + u8 i; + u32 data, strap, index; + + if (*condition) { + + strap = gk20a_readl(g, gc6_sci_strap_r()) & 0xf; + + index = g->bios.mem_strap_xlat_tbl_ptr ? + gm206_bios_read_u8(g, g->bios.mem_strap_xlat_tbl_ptr + + strap) : strap; + + for (i = 0; i < count; i++) { + data = gm206_bios_read_u32(g, data_table_offset + ((i * + g->bios.mem_strap_data_count + index) * + sizeof(u32))); + gk20a_writel(g, reg, data); + reg += stride; + } + } +} + +static void gp106_init_condition(struct gk20a *g, bool *condition, + u32 condition_id) +{ + struct condition_entry entry; + + entry.cond_addr = gm206_bios_read_u32(g, g->bios.condition_table_ptr + + sizeof(entry)*condition_id); + entry.cond_mask = gm206_bios_read_u32(g, g->bios.condition_table_ptr + + sizeof(entry)*condition_id + 4); + entry.cond_compare = gm206_bios_read_u32(g, g->bios.condition_table_ptr + + sizeof(entry)*condition_id + 8); + + if ((gk20a_readl(g, entry.cond_addr) & entry.cond_mask) + != entry.cond_compare) { + *condition = false; + } +} + +static int gp106_execute_script(struct gk20a *g, u32 offset) +{ + u8 opcode; + u32 ip; + u32 operand[8]; + bool condition, end; + int status = 0; + + ip = offset; + condition = true; + end = false; + + while (!end) { + + opcode = gm206_bios_read_u8(g, ip++); + + switch (opcode) { + + case INIT_XMEMSEL_ZM_NV_REG_ARRAY: + operand[0] = gm206_bios_read_u32(g, ip); + operand[1] = gm206_bios_read_u8(g, ip+4); + operand[2] = gm206_bios_read_u8(g, ip+5); + ip += 6; + + gp106_init_xmemsel_zm_nv_reg_array(g, &condition, + operand[0], operand[1], operand[2], ip); + ip += operand[2] * sizeof(u32) * + g->bios.mem_strap_data_count; + break; + + case INIT_CONDITION: + operand[0] = gm206_bios_read_u8(g, ip); + ip++; + + gp106_init_condition(g, &condition, operand[0]); + break; + + case INIT_RESUME: + condition = true; + break; + + case INIT_DONE: + end = true; + break; + + default: + gk20a_err(dev_from_gk20a(g), "opcode: 0x%02x", opcode); + end = true; + status = -EINVAL; + break; + } + } + + return status; +} + +void gp106_init_bios(struct gpu_ops *gops) +{ + gm206_init_bios(gops); + gops->bios.execute_script = gp106_execute_script; +} -- cgit v1.2.2