summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/clk/clk_mclk.c
diff options
context:
space:
mode:
authorDavid Nieto <dmartineznie@nvidia.com>2016-08-19 20:09:35 -0400
committerDeepak Nibade <dnibade@nvidia.com>2016-12-27 04:56:50 -0500
commit905f1c0392bf244b321f56f82661eeb2fe00ee05 (patch)
treed525a6d5554b537e0a34ca7917c90364176dbb2e /drivers/gpu/nvgpu/clk/clk_mclk.c
parent4a94ce451b0352ce67e11a2971bbbd75c2e58df1 (diff)
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 <dmartineznie@nvidia.com> Reviewed-on: http://git-master/r/1214956 Reviewed-on: http://git-master/r/1237293 Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/clk/clk_mclk.c')
-rw-r--r--drivers/gpu/nvgpu/clk/clk_mclk.c278
1 files changed, 193 insertions, 85 deletions
diff --git a/drivers/gpu/nvgpu/clk/clk_mclk.c b/drivers/gpu/nvgpu/clk/clk_mclk.c
index df010221..b63fab1e 100644
--- a/drivers/gpu/nvgpu/clk/clk_mclk.c
+++ b/drivers/gpu/nvgpu/clk/clk_mclk.c
@@ -17,6 +17,9 @@
17#include "gm206/bios_gm206.h" 17#include "gm206/bios_gm206.h"
18#include "gk20a/pmu_gk20a.h" 18#include "gk20a/pmu_gk20a.h"
19#include "gk20a/hw_pwr_gk20a.h" 19#include "gk20a/hw_pwr_gk20a.h"
20#include "gp106/hw_fb_gp106.h"
21
22#include "include/bios.h"
20 23
21#define VREG_COUNT 24 24#define VREG_COUNT 24
22 25
@@ -29,63 +32,6 @@ struct memory_link_training_pattern {
29 u32 writeval; 32 u32 writeval;
30}; 33};
31 34
32static struct memory_link_training_pattern memory_shadow_p0_reglist[] = {
33 {0x9a065c, 0x20},
34 {0x98467c, 0xffff0000},
35 {0x984708, 0x30550},
36 {0x98470c, 0x4C4C},
37 {0x9006a0, 0x03030303},
38 {0x9006a4, 0x03030303},
39 {0x9046a0, 0x03030303},
40 {0x9046a4, 0x03030303},
41 {0x9086a0, 0x03030303},
42 {0x9086a4, 0x03030303},
43 {0x9846a8, 0x03030303},
44 {0x9846ac, 0x03030303},
45 {0x9a065c, 0x00},
46};
47
48static struct memory_link_training_pattern memory_shadow_p5_reglist[] = {
49 {0x9a065c, 0x10},
50 {0x98467c, 0xfff10000},
51 {0x984708, 0x30002},
52 {0x98470c, 0x1414},
53 {0x9006a0, 0x12121212},
54 {0x9006a4, 0x12121212},
55 {0x9046a0, 0x12121212},
56 {0x9046a4, 0x12121212},
57 {0x9086a0, 0x12121212},
58 {0x9086a4, 0x12121212},
59 {0x90c6a0, 0x12121212},
60 {0x90c6a4, 0x12121212},
61 {0x9106a0, 0x12121212},
62 {0x9106a4, 0x12121212},
63 {0x9146a0, 0x12121212},
64 {0x9146a4, 0x12121212},
65 {0x9a065c, 0x0},
66 {0x9a08e0, 0x10},
67 {0x9846a8, 0x0f0f0f0f},
68 {0x9846ac, 0x0f0f0f0f},
69 {0x984d98, 0x22222222},
70 {0x984d9c, 0x22222222},
71 {0x984da0, 0x22222222},
72 {0x984da4, 0x22222222},
73 {0x984da8, 0x22222222},
74 {0x984dac, 0x22222222},
75 {0x984dac, 0x22222222},
76 {0x984d70, 0x0},
77 {0x984d74, 0x0},
78 {0x984d78, 0x0},
79 {0x984d7c, 0x0},
80 {0x984d80, 0x0},
81 {0x984d84, 0x0},
82 {0x984d88, 0x0},
83 {0x984d8c, 0x0},
84 {0x984d90, 0x0},
85 {0x984d94, 0x0},
86 {0x9a08e0, 0x0},
87};
88
89static struct memory_link_training_pattern memory_pattern_reglist[] = { 35static struct memory_link_training_pattern memory_pattern_reglist[] = {
90 {0x9a0968, 0x0}, 36 {0x9a0968, 0x0},
91 {0x9a0920, 0x0}, 37 {0x9a0920, 0x0},
@@ -2026,31 +1972,6 @@ static void mclk_memory_load_training_pattern(struct gk20a *g)
2026 gk20a_dbg_fn("done"); 1972 gk20a_dbg_fn("done");
2027} 1973}
2028 1974
2029static void mclk_memory_load_shadow_regs(struct gk20a *g)
2030{
2031 u32 reg_writes;
2032 u32 index;
2033
2034 gk20a_dbg_info("");
2035
2036 reg_writes = ((sizeof(memory_shadow_p0_reglist) /
2037 sizeof((memory_shadow_p0_reglist)[0])));
2038 for (index = 0; index < reg_writes; index++) {
2039 gk20a_writel(g, memory_shadow_p0_reglist[index].regaddr,
2040 memory_shadow_p0_reglist[index].writeval);
2041 }
2042
2043 reg_writes = ((sizeof(memory_shadow_p5_reglist) /
2044 sizeof((memory_shadow_p5_reglist)[0])));
2045 for (index = 0; index < reg_writes; index++) {
2046 gk20a_writel(g, memory_shadow_p5_reglist[index].regaddr,
2047 memory_shadow_p5_reglist[index].writeval);
2048 }
2049
2050 gk20a_dbg_fn("done");
2051
2052}
2053
2054static void mclk_seq_pmucmdhandler(struct gk20a *g, struct pmu_msg *_msg, 1975static void mclk_seq_pmucmdhandler(struct gk20a *g, struct pmu_msg *_msg,
2055 void *param, u32 handle, u32 status) 1976 void *param, u32 handle, u32 status)
2056{ 1977{
@@ -2082,9 +2003,189 @@ status_update:
2082 *((u32 *)param) = msg_status; 2003 *((u32 *)param) = msg_status;
2083} 2004}
2084 2005
2006static int mclk_get_memclk_table(struct gk20a *g)
2007{
2008 int status = 0;
2009 u8 *mem_table_ptr = NULL;
2010 u32 idx_to_ptr_tbl[8];
2011 u32 idx_to_cmd_ptr_tbl[8];
2012
2013 u32 old_fbio_delay;
2014 u32 old_fbio_cmd_delay;
2015
2016 u32 cmd_idx;
2017 u32 shadow_idx;
2018
2019 struct vbios_memory_clock_header_1x memclock_table_header = { 0 };
2020 struct vbios_memory_clock_base_entry_11 memclock_base_entry = { 0 };
2021
2022 u8 *mem_entry_ptr = NULL;
2023 int index;
2024
2025 gk20a_dbg_info("");
2026
2027 if (!(g->ops.bios.get_perf_table_ptrs &&
2028 g->ops.bios.execute_script)) {
2029 goto done;
2030 }
2031
2032 mem_table_ptr = (u8 *)g->ops.bios.get_perf_table_ptrs(g,
2033 g->bios.perf_token,
2034 MEMORY_CLOCK_TABLE);
2035 if (mem_table_ptr == NULL) {
2036 status = -EPERM;
2037 goto done;
2038 }
2039
2040 memcpy(&memclock_table_header, mem_table_ptr,
2041 sizeof(memclock_table_header));
2042
2043 if ((memclock_table_header.version <
2044 VBIOS_MEMORY_CLOCK_HEADER_11_VERSION) ||
2045 (memclock_table_header.base_entry_size <
2046 VBIOS_MEMORY_CLOCK_BASE_ENTRY_11_2_SIZE)) {
2047 status = -EINVAL;
2048 goto done;
2049 }
2050
2051 /* reset and save shadow table map and registers */
2052 old_fbio_delay = gk20a_readl(g, fb_fbpa_fbio_delay_r());
2053 old_fbio_cmd_delay = gk20a_readl(g, fb_fbpa_fbio_cmd_delay_r());
2054
2055 memset(idx_to_ptr_tbl, 0, sizeof(idx_to_ptr_tbl));
2056 memset(idx_to_cmd_ptr_tbl, 0, sizeof(idx_to_cmd_ptr_tbl));
2057
2058 /* Read table entries */
2059 mem_entry_ptr = mem_table_ptr + memclock_table_header.header_size;
2060 for (index = 0; index < memclock_table_header.entry_count; index++) {
2061 u8 script_index, cmd_script_index;
2062 u32 script_ptr = 0, cmd_script_ptr = 0;
2063
2064 memcpy(&memclock_base_entry, mem_entry_ptr,
2065 memclock_table_header.base_entry_size);
2066 if (memclock_base_entry.maximum == 0)
2067 continue;
2068
2069 script_index = BIOS_GET_FIELD(memclock_base_entry.flags1,
2070 VBIOS_MEMORY_CLOCK_BASE_ENTRY_11_FLAGS1_SCRIPT_INDEX);
2071
2072 script_ptr = gm206_bios_read_u32(g,
2073 memclock_table_header.script_list_ptr +
2074 script_index * sizeof(u32));
2075
2076 if (!script_ptr)
2077 continue;
2078
2079 /* Link and execute shadow scripts */
2080
2081 for (shadow_idx = 0; shadow_idx <= fb_fbpa_fbio_delay_priv_max_v();
2082 ++shadow_idx) {
2083 if (script_ptr == idx_to_ptr_tbl[shadow_idx]) {
2084 break;
2085 }
2086 }
2087
2088 /* script has not been executed before */
2089 if (shadow_idx > fb_fbpa_fbio_delay_priv_max_v()) {
2090 /* find unused index */
2091 for (shadow_idx = 0; shadow_idx <
2092 fb_fbpa_fbio_delay_priv_max_v();
2093 ++shadow_idx) {
2094 if (idx_to_ptr_tbl[shadow_idx] == 0)
2095 break;
2096 }
2097
2098 if (shadow_idx > fb_fbpa_fbio_delay_priv_max_v()) {
2099 gk20a_err(dev_from_gk20a(g),
2100 "invalid shadow reg script index");
2101 status = -EINVAL;
2102 goto done;
2103 }
2104
2105 idx_to_ptr_tbl[shadow_idx] = script_ptr;
2106
2107 gk20a_writel(g, fb_fbpa_fbio_delay_r(),
2108 set_field(old_fbio_delay,
2109 fb_fbpa_fbio_delay_priv_m(),
2110 fb_fbpa_fbio_delay_priv_f(shadow_idx)));
2111
2112 status = g->ops.bios.execute_script(g, script_ptr);
2113 if (status < 0) {
2114 gk20a_writel(g, fb_fbpa_fbio_delay_r(),
2115 old_fbio_delay);
2116 goto done;
2117 }
2118
2119 gk20a_writel(g, fb_fbpa_fbio_delay_r(), old_fbio_delay);
2120
2121 }
2122
2123 cmd_script_index = BIOS_GET_FIELD(memclock_base_entry.flags2,
2124 VBIOS_MEMORY_CLOCK_BASE_ENTRY_12_FLAGS2_CMD_SCRIPT_INDEX);
2125
2126 cmd_script_ptr = gm206_bios_read_u32(g,
2127 memclock_table_header.cmd_script_list_ptr +
2128 cmd_script_index * sizeof(u32));
2129
2130 if (!cmd_script_ptr)
2131 continue;
2132
2133 /* Link and execute cmd shadow scripts */
2134 for (cmd_idx = 0; cmd_idx <= fb_fbpa_fbio_cmd_delay_cmd_priv_max_v();
2135 ++cmd_idx) {
2136 if (cmd_script_ptr == idx_to_cmd_ptr_tbl[cmd_idx])
2137 break;
2138 }
2139
2140 /* script has not been executed before */
2141 if (cmd_idx > fb_fbpa_fbio_cmd_delay_cmd_priv_max_v()) {
2142 /* find unused index */
2143 for (cmd_idx = 0; cmd_idx <
2144 fb_fbpa_fbio_cmd_delay_cmd_priv_max_v();
2145 ++cmd_idx) {
2146 if (idx_to_cmd_ptr_tbl[cmd_idx] == 0)
2147 break;
2148 }
2149
2150 if (cmd_idx > fb_fbpa_fbio_cmd_delay_cmd_priv_max_v()) {
2151 gk20a_err(dev_from_gk20a(g),
2152 "invalid shadow reg cmd script index");
2153 status = -EINVAL;
2154 goto done;
2155 }
2156
2157 idx_to_cmd_ptr_tbl[cmd_idx] = cmd_script_ptr;
2158 gk20a_writel(g, fb_fbpa_fbio_cmd_delay_r(),
2159 set_field(old_fbio_cmd_delay,
2160 fb_fbpa_fbio_cmd_delay_cmd_priv_m(),
2161 fb_fbpa_fbio_cmd_delay_cmd_priv_f(
2162 cmd_idx)));
2163
2164 status = g->ops.bios.execute_script(g, cmd_script_ptr);
2165 if (status < 0) {
2166 gk20a_writel(g, fb_fbpa_fbio_cmd_delay_r(),
2167 old_fbio_cmd_delay);
2168 goto done;
2169 }
2170
2171 gk20a_writel(g, fb_fbpa_fbio_cmd_delay_r(),
2172 old_fbio_cmd_delay);
2173
2174 }
2175
2176 mem_entry_ptr += memclock_table_header.base_entry_size +
2177 memclock_table_header.strap_entry_count *
2178 memclock_table_header.strap_entry_size;
2179 }
2180
2181done:
2182 return status;
2183}
2184
2085int clk_mclkseq_init_mclk_gddr5(struct gk20a *g) 2185int clk_mclkseq_init_mclk_gddr5(struct gk20a *g)
2086{ 2186{
2087 struct clk_mclk_state *mclk; 2187 struct clk_mclk_state *mclk;
2188 int status;
2088 2189
2089 gk20a_dbg_fn(""); 2190 gk20a_dbg_fn("");
2090 2191
@@ -2094,8 +2195,10 @@ int clk_mclkseq_init_mclk_gddr5(struct gk20a *g)
2094 2195
2095 mclk->speed = gk20a_mclk_low_speed; /* Value from Devinit */ 2196 mclk->speed = gk20a_mclk_low_speed; /* Value from Devinit */
2096 2197
2097 /* Load Shadow registers */ 2198 /* Parse VBIOS */
2098 mclk_memory_load_shadow_regs(g); 2199 status = mclk_get_memclk_table(g);
2200 if (status < 0)
2201 return status;
2099 2202
2100 /* Load RAM pattern */ 2203 /* Load RAM pattern */
2101 mclk_memory_load_training_pattern(g); 2204 mclk_memory_load_training_pattern(g);
@@ -2115,6 +2218,8 @@ int clk_mclkseq_init_mclk_gddr5(struct gk20a *g)
2115#endif 2218#endif
2116 mclk->change = clk_mclkseq_change_mclk_gddr5; 2219 mclk->change = clk_mclkseq_change_mclk_gddr5;
2117 2220
2221 mclk->init = true;
2222
2118 return mclk->change(g, DEFAULT_BOOT_MCLK_SPEED); 2223 return mclk->change(g, DEFAULT_BOOT_MCLK_SPEED);
2119} 2224}
2120 2225
@@ -2125,7 +2230,7 @@ int clk_mclkseq_change_mclk_gddr5(struct gk20a *g, enum gk20a_mclk_speed speed)
2125 struct nv_pmu_seq_cmd cmd; 2230 struct nv_pmu_seq_cmd cmd;
2126 struct nv_pmu_seq_cmd_run_script *pseq_cmd; 2231 struct nv_pmu_seq_cmd_run_script *pseq_cmd;
2127 u32 seqdesc; 2232 u32 seqdesc;
2128 u32 status = 0; 2233 int status = 0;
2129 u32 seq_completion_status = ~0x0; 2234 u32 seq_completion_status = ~0x0;
2130 u8 *seq_script_ptr = NULL; 2235 u8 *seq_script_ptr = NULL;
2131 size_t seq_script_size = 0; 2236 size_t seq_script_size = 0;
@@ -2139,6 +2244,9 @@ int clk_mclkseq_change_mclk_gddr5(struct gk20a *g, enum gk20a_mclk_speed speed)
2139 2244
2140 mutex_lock(&mclk->mclk_mutex); 2245 mutex_lock(&mclk->mclk_mutex);
2141 2246
2247 if (!mclk->init)
2248 goto exit_status;
2249
2142 if (speed == mclk->speed) 2250 if (speed == mclk->speed)
2143 goto exit_status; 2251 goto exit_status;
2144 2252