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 +++++++++++++++++++++++++++++++++ drivers/gpu/nvgpu/gp106/bios_gp106.h | 31 +++++++++ drivers/gpu/nvgpu/gp106/hal_gp106.c | 4 +- drivers/gpu/nvgpu/gp106/hw_fb_gp106.h | 72 ++++++++++++++++++++ drivers/gpu/nvgpu/gp106/hw_gc6_gp106.h | 56 +++++++++++++++ 5 files changed, 282 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/nvgpu/gp106/bios_gp106.c create mode 100644 drivers/gpu/nvgpu/gp106/bios_gp106.h create mode 100644 drivers/gpu/nvgpu/gp106/hw_gc6_gp106.h (limited to 'drivers/gpu/nvgpu/gp106') 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; +} diff --git a/drivers/gpu/nvgpu/gp106/bios_gp106.h b/drivers/gpu/nvgpu/gp106/bios_gp106.h new file mode 100644 index 00000000..f47d11ca --- /dev/null +++ b/drivers/gpu/nvgpu/gp106/bios_gp106.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 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. + */ + +#ifndef NVGPU_BIOS_GP106_H +#define NVGPU_BIOS_GP106_H + +struct gpu_ops; + +#define INIT_DONE 0x71 +#define INIT_RESUME 0x72 +#define INIT_CONDITION 0x75 +#define INIT_XMEMSEL_ZM_NV_REG_ARRAY 0x8f + +struct condition_entry { + u32 cond_addr; + u32 cond_mask; + u32 cond_compare; +} __packed; + +void gp106_init_bios(struct gpu_ops *gops); +#endif diff --git a/drivers/gpu/nvgpu/gp106/hal_gp106.c b/drivers/gpu/nvgpu/gp106/hal_gp106.c index 2217dfea..89e0e1fd 100644 --- a/drivers/gpu/nvgpu/gp106/hal_gp106.c +++ b/drivers/gpu/nvgpu/gp106/hal_gp106.c @@ -31,7 +31,7 @@ #include "gp106/therm_gp106.h" #include "gp106/xve_gp106.h" -#include "gm206/bios_gm206.h" +#include "gp106/bios_gp106.h" #include "gm20b/gr_gm20b.h" #include "gm20b/fifo_gm20b.h" @@ -209,7 +209,7 @@ int gp106_init_hal(struct gk20a *g) #if defined(CONFIG_GK20A_CYCLE_STATS) gk20a_init_css_ops(gops); #endif - gm206_init_bios(gops); + gp106_init_bios(gops); gp106_init_therm_ops(gops); gp106_init_xve_ops(gops); diff --git a/drivers/gpu/nvgpu/gp106/hw_fb_gp106.h b/drivers/gpu/nvgpu/gp106/hw_fb_gp106.h index 1ab876cd..d76f78b9 100644 --- a/drivers/gpu/nvgpu/gp106/hw_fb_gp106.h +++ b/drivers/gpu/nvgpu/gp106/hw_fb_gp106.h @@ -502,4 +502,76 @@ static inline u32 fb_mmu_local_memory_range_ecc_mode_v(u32 r) { return (r >> 30) & 0x1; } +static inline u32 fb_fbpa_fbio_delay_r(void) +{ + return 0x9a065c; +} +static inline u32 fb_fbpa_fbio_delay_src_m(void) +{ + return 0x7; +} +static inline u32 fb_fbpa_fbio_delay_src_v(u32 r) +{ + return (r >> 0) & 0x7; +} +static inline u32 fb_fbpa_fbio_delay_src_f(u32 v) +{ + return (v & 0x7) << 0; +} +static inline u32 fb_fbpa_fbio_delay_src_max_v(void) +{ + return 2; +} +static inline u32 fb_fbpa_fbio_delay_priv_m(void) +{ + return 0x7 << 4; +} +static inline u32 fb_fbpa_fbio_delay_priv_v(u32 r) +{ + return (r >> 4) & 0x7; +} +static inline u32 fb_fbpa_fbio_delay_priv_f(u32 v) +{ + return (v & 0x7) << 4; +} +static inline u32 fb_fbpa_fbio_delay_priv_max_v(void) +{ + return 2; +} +static inline u32 fb_fbpa_fbio_cmd_delay_r(void) +{ + return 0x9a08e0; +} +static inline u32 fb_fbpa_fbio_cmd_delay_cmd_src_m(void) +{ + return 0x7; +} +static inline u32 fb_fbpa_fbio_cmd_delay_cmd_src_v(u32 r) +{ + return (r >> 0) & 0x7; +} +static inline u32 fb_fbpa_fbio_cmd_delay_cmd_src_f(u32 v) +{ + return (v & 0x7) << 0; +} +static inline u32 fb_fbpa_fbio_cmd_delay_cmd_src_max_v(void) +{ + return 1; +} +static inline u32 fb_fbpa_fbio_cmd_delay_cmd_priv_m(void) +{ + return 0x7 << 4; +} +static inline u32 fb_fbpa_fbio_cmd_delay_cmd_priv_v(u32 r) +{ + return (r >> 4) & 0x7; +} +static inline u32 fb_fbpa_fbio_cmd_delay_cmd_priv_f(u32 v) +{ + return (v & 0x7) << 4; +} +static inline u32 fb_fbpa_fbio_cmd_delay_cmd_priv_max_v(void) +{ + return 1; +} #endif diff --git a/drivers/gpu/nvgpu/gp106/hw_gc6_gp106.h b/drivers/gpu/nvgpu/gp106/hw_gc6_gp106.h new file mode 100644 index 00000000..25aca9b5 --- /dev/null +++ b/drivers/gpu/nvgpu/gp106/hw_gc6_gp106.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/* + * Function naming determines intended use: + * + * _r(void) : Returns the offset for register . + * + * _o(void) : Returns the offset for element . + * + * _w(void) : Returns the word offset for word (4 byte) element . + * + * __s(void) : Returns size of field of register in bits. + * + * __f(u32 v) : Returns a value based on 'v' which has been shifted + * and masked to place it at field of register . This value + * can be |'d with others to produce a full register value for + * register . + * + * __m(void) : Returns a mask for field of register . This + * value can be ~'d and then &'d to clear the value of field for + * register . + * + * ___f(void) : Returns the constant value after being shifted + * to place it at field of register . This value can be |'d + * with others to produce a full register value for . + * + * __v(u32 r) : Returns the value of field from a full register + * value 'r' after being shifted to place its LSB at bit 0. + * This value is suitable for direct comparison with other unshifted + * values appropriate for use in field of register . + * + * ___v(void) : Returns the constant value for defined for + * field of register . This value is suitable for direct + * comparison with unshifted values appropriate for use in field + * of register . + */ +#ifndef _hw_gc6_gp106_h_ +#define _hw_gc6_gp106_h_ +static inline u32 gc6_sci_strap_r(void) +{ + return 0x00010ebb0; +} +#endif -- cgit v1.2.2