diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/Makefile.nvgpu-t18x | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk_mclk.c | 278 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/clk/clk_mclk.h | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp106/bios_gp106.c | 121 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp106/bios_gp106.h | 31 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp106/hal_gp106.c | 4 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp106/hw_fb_gp106.h | 72 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp106/hw_gc6_gp106.h | 56 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/include/bios.h | 94 |
9 files changed, 572 insertions, 88 deletions
diff --git a/drivers/gpu/nvgpu/Makefile.nvgpu-t18x b/drivers/gpu/nvgpu/Makefile.nvgpu-t18x index 17b33959..ceae6006 100644 --- a/drivers/gpu/nvgpu/Makefile.nvgpu-t18x +++ b/drivers/gpu/nvgpu/Makefile.nvgpu-t18x | |||
@@ -29,6 +29,7 @@ nvgpu-y += \ | |||
29 | $(nvgpu-t18x)/gp106/fifo_gp106.o \ | 29 | $(nvgpu-t18x)/gp106/fifo_gp106.o \ |
30 | $(nvgpu-t18x)/gp106/ltc_gp106.o \ | 30 | $(nvgpu-t18x)/gp106/ltc_gp106.o \ |
31 | $(nvgpu-t18x)/gp106/fb_gp106.o \ | 31 | $(nvgpu-t18x)/gp106/fb_gp106.o \ |
32 | $(nvgpu-t18x)/gp106/bios_gp106.o \ | ||
32 | $(nvgpu-t18x)/clk/clk_mclk.o \ | 33 | $(nvgpu-t18x)/clk/clk_mclk.o \ |
33 | $(nvgpu-t18x)/pstate/pstate.o \ | 34 | $(nvgpu-t18x)/pstate/pstate.o \ |
34 | $(nvgpu-t18x)/clk/clk_vin.o \ | 35 | $(nvgpu-t18x)/clk/clk_vin.o \ |
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 | ||
32 | static 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 | |||
48 | static 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 | |||
89 | static struct memory_link_training_pattern memory_pattern_reglist[] = { | 35 | static 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 | ||
2029 | static 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 | |||
2054 | static void mclk_seq_pmucmdhandler(struct gk20a *g, struct pmu_msg *_msg, | 1975 | static 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 | ||
2006 | static 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 | |||
2181 | done: | ||
2182 | return status; | ||
2183 | } | ||
2184 | |||
2085 | int clk_mclkseq_init_mclk_gddr5(struct gk20a *g) | 2185 | int 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 | ||
diff --git a/drivers/gpu/nvgpu/clk/clk_mclk.h b/drivers/gpu/nvgpu/clk/clk_mclk.h index c3261eac..edb7eb78 100644 --- a/drivers/gpu/nvgpu/clk/clk_mclk.h +++ b/drivers/gpu/nvgpu/clk/clk_mclk.h | |||
@@ -19,13 +19,14 @@ | |||
19 | enum gk20a_mclk_speed { | 19 | enum gk20a_mclk_speed { |
20 | gk20a_mclk_low_speed, | 20 | gk20a_mclk_low_speed, |
21 | gk20a_mclk_mid_speed, | 21 | gk20a_mclk_mid_speed, |
22 | gk20a_mclk_high_speed | 22 | gk20a_mclk_high_speed, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | struct clk_mclk_state { | 25 | struct clk_mclk_state { |
26 | enum gk20a_mclk_speed speed; | 26 | enum gk20a_mclk_speed speed; |
27 | struct mutex mclk_mutex; | 27 | struct mutex mclk_mutex; |
28 | void *vreg_buf; | 28 | void *vreg_buf; |
29 | bool init; | ||
29 | 30 | ||
30 | /* function pointers */ | 31 | /* function pointers */ |
31 | int (*change)(struct gk20a *g, enum gk20a_mclk_speed speed); | 32 | int (*change)(struct gk20a *g, enum gk20a_mclk_speed speed); |
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 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | */ | ||
13 | |||
14 | #include "gk20a/gk20a.h" | ||
15 | #include "gm206/bios_gm206.h" | ||
16 | #include "bios_gp106.h" | ||
17 | #include "hw_gc6_gp106.h" | ||
18 | |||
19 | static void gp106_init_xmemsel_zm_nv_reg_array(struct gk20a *g, bool *condition, | ||
20 | u32 reg, u32 stride, u32 count, u32 data_table_offset) | ||
21 | { | ||
22 | u8 i; | ||
23 | u32 data, strap, index; | ||
24 | |||
25 | if (*condition) { | ||
26 | |||
27 | strap = gk20a_readl(g, gc6_sci_strap_r()) & 0xf; | ||
28 | |||
29 | index = g->bios.mem_strap_xlat_tbl_ptr ? | ||
30 | gm206_bios_read_u8(g, g->bios.mem_strap_xlat_tbl_ptr + | ||
31 | strap) : strap; | ||
32 | |||
33 | for (i = 0; i < count; i++) { | ||
34 | data = gm206_bios_read_u32(g, data_table_offset + ((i * | ||
35 | g->bios.mem_strap_data_count + index) * | ||
36 | sizeof(u32))); | ||
37 | gk20a_writel(g, reg, data); | ||
38 | reg += stride; | ||
39 | } | ||
40 | } | ||
41 | } | ||
42 | |||
43 | static void gp106_init_condition(struct gk20a *g, bool *condition, | ||
44 | u32 condition_id) | ||
45 | { | ||
46 | struct condition_entry entry; | ||
47 | |||
48 | entry.cond_addr = gm206_bios_read_u32(g, g->bios.condition_table_ptr + | ||
49 | sizeof(entry)*condition_id); | ||
50 | entry.cond_mask = gm206_bios_read_u32(g, g->bios.condition_table_ptr + | ||
51 | sizeof(entry)*condition_id + 4); | ||
52 | entry.cond_compare = gm206_bios_read_u32(g, g->bios.condition_table_ptr + | ||
53 | sizeof(entry)*condition_id + 8); | ||
54 | |||
55 | if ((gk20a_readl(g, entry.cond_addr) & entry.cond_mask) | ||
56 | != entry.cond_compare) { | ||
57 | *condition = false; | ||
58 | } | ||
59 | } | ||
60 | |||
61 | static int gp106_execute_script(struct gk20a *g, u32 offset) | ||
62 | { | ||
63 | u8 opcode; | ||
64 | u32 ip; | ||
65 | u32 operand[8]; | ||
66 | bool condition, end; | ||
67 | int status = 0; | ||
68 | |||
69 | ip = offset; | ||
70 | condition = true; | ||
71 | end = false; | ||
72 | |||
73 | while (!end) { | ||
74 | |||
75 | opcode = gm206_bios_read_u8(g, ip++); | ||
76 | |||
77 | switch (opcode) { | ||
78 | |||
79 | case INIT_XMEMSEL_ZM_NV_REG_ARRAY: | ||
80 | operand[0] = gm206_bios_read_u32(g, ip); | ||
81 | operand[1] = gm206_bios_read_u8(g, ip+4); | ||
82 | operand[2] = gm206_bios_read_u8(g, ip+5); | ||
83 | ip += 6; | ||
84 | |||
85 | gp106_init_xmemsel_zm_nv_reg_array(g, &condition, | ||
86 | operand[0], operand[1], operand[2], ip); | ||
87 | ip += operand[2] * sizeof(u32) * | ||
88 | g->bios.mem_strap_data_count; | ||
89 | break; | ||
90 | |||
91 | case INIT_CONDITION: | ||
92 | operand[0] = gm206_bios_read_u8(g, ip); | ||
93 | ip++; | ||
94 | |||
95 | gp106_init_condition(g, &condition, operand[0]); | ||
96 | break; | ||
97 | |||
98 | case INIT_RESUME: | ||
99 | condition = true; | ||
100 | break; | ||
101 | |||
102 | case INIT_DONE: | ||
103 | end = true; | ||
104 | break; | ||
105 | |||
106 | default: | ||
107 | gk20a_err(dev_from_gk20a(g), "opcode: 0x%02x", opcode); | ||
108 | end = true; | ||
109 | status = -EINVAL; | ||
110 | break; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | return status; | ||
115 | } | ||
116 | |||
117 | void gp106_init_bios(struct gpu_ops *gops) | ||
118 | { | ||
119 | gm206_init_bios(gops); | ||
120 | gops->bios.execute_script = gp106_execute_script; | ||
121 | } | ||
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 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | */ | ||
13 | |||
14 | #ifndef NVGPU_BIOS_GP106_H | ||
15 | #define NVGPU_BIOS_GP106_H | ||
16 | |||
17 | struct gpu_ops; | ||
18 | |||
19 | #define INIT_DONE 0x71 | ||
20 | #define INIT_RESUME 0x72 | ||
21 | #define INIT_CONDITION 0x75 | ||
22 | #define INIT_XMEMSEL_ZM_NV_REG_ARRAY 0x8f | ||
23 | |||
24 | struct condition_entry { | ||
25 | u32 cond_addr; | ||
26 | u32 cond_mask; | ||
27 | u32 cond_compare; | ||
28 | } __packed; | ||
29 | |||
30 | void gp106_init_bios(struct gpu_ops *gops); | ||
31 | #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 @@ | |||
31 | #include "gp106/therm_gp106.h" | 31 | #include "gp106/therm_gp106.h" |
32 | #include "gp106/xve_gp106.h" | 32 | #include "gp106/xve_gp106.h" |
33 | 33 | ||
34 | #include "gm206/bios_gm206.h" | 34 | #include "gp106/bios_gp106.h" |
35 | 35 | ||
36 | #include "gm20b/gr_gm20b.h" | 36 | #include "gm20b/gr_gm20b.h" |
37 | #include "gm20b/fifo_gm20b.h" | 37 | #include "gm20b/fifo_gm20b.h" |
@@ -209,7 +209,7 @@ int gp106_init_hal(struct gk20a *g) | |||
209 | #if defined(CONFIG_GK20A_CYCLE_STATS) | 209 | #if defined(CONFIG_GK20A_CYCLE_STATS) |
210 | gk20a_init_css_ops(gops); | 210 | gk20a_init_css_ops(gops); |
211 | #endif | 211 | #endif |
212 | gm206_init_bios(gops); | 212 | gp106_init_bios(gops); |
213 | gp106_init_therm_ops(gops); | 213 | gp106_init_therm_ops(gops); |
214 | gp106_init_xve_ops(gops); | 214 | gp106_init_xve_ops(gops); |
215 | 215 | ||
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) | |||
502 | { | 502 | { |
503 | return (r >> 30) & 0x1; | 503 | return (r >> 30) & 0x1; |
504 | } | 504 | } |
505 | static inline u32 fb_fbpa_fbio_delay_r(void) | ||
506 | { | ||
507 | return 0x9a065c; | ||
508 | } | ||
509 | static inline u32 fb_fbpa_fbio_delay_src_m(void) | ||
510 | { | ||
511 | return 0x7; | ||
512 | } | ||
513 | static inline u32 fb_fbpa_fbio_delay_src_v(u32 r) | ||
514 | { | ||
515 | return (r >> 0) & 0x7; | ||
516 | } | ||
517 | static inline u32 fb_fbpa_fbio_delay_src_f(u32 v) | ||
518 | { | ||
519 | return (v & 0x7) << 0; | ||
520 | } | ||
521 | static inline u32 fb_fbpa_fbio_delay_src_max_v(void) | ||
522 | { | ||
523 | return 2; | ||
524 | } | ||
525 | static inline u32 fb_fbpa_fbio_delay_priv_m(void) | ||
526 | { | ||
527 | return 0x7 << 4; | ||
528 | } | ||
529 | static inline u32 fb_fbpa_fbio_delay_priv_v(u32 r) | ||
530 | { | ||
531 | return (r >> 4) & 0x7; | ||
532 | } | ||
533 | static inline u32 fb_fbpa_fbio_delay_priv_f(u32 v) | ||
534 | { | ||
535 | return (v & 0x7) << 4; | ||
536 | } | ||
537 | static inline u32 fb_fbpa_fbio_delay_priv_max_v(void) | ||
538 | { | ||
539 | return 2; | ||
540 | } | ||
541 | static inline u32 fb_fbpa_fbio_cmd_delay_r(void) | ||
542 | { | ||
543 | return 0x9a08e0; | ||
544 | } | ||
545 | static inline u32 fb_fbpa_fbio_cmd_delay_cmd_src_m(void) | ||
546 | { | ||
547 | return 0x7; | ||
548 | } | ||
549 | static inline u32 fb_fbpa_fbio_cmd_delay_cmd_src_v(u32 r) | ||
550 | { | ||
551 | return (r >> 0) & 0x7; | ||
552 | } | ||
553 | static inline u32 fb_fbpa_fbio_cmd_delay_cmd_src_f(u32 v) | ||
554 | { | ||
555 | return (v & 0x7) << 0; | ||
556 | } | ||
557 | static inline u32 fb_fbpa_fbio_cmd_delay_cmd_src_max_v(void) | ||
558 | { | ||
559 | return 1; | ||
560 | } | ||
561 | static inline u32 fb_fbpa_fbio_cmd_delay_cmd_priv_m(void) | ||
562 | { | ||
563 | return 0x7 << 4; | ||
564 | } | ||
565 | static inline u32 fb_fbpa_fbio_cmd_delay_cmd_priv_v(u32 r) | ||
566 | { | ||
567 | return (r >> 4) & 0x7; | ||
568 | } | ||
569 | static inline u32 fb_fbpa_fbio_cmd_delay_cmd_priv_f(u32 v) | ||
570 | { | ||
571 | return (v & 0x7) << 4; | ||
572 | } | ||
573 | static inline u32 fb_fbpa_fbio_cmd_delay_cmd_priv_max_v(void) | ||
574 | { | ||
575 | return 1; | ||
576 | } | ||
505 | #endif | 577 | #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 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | /* | ||
17 | * Function naming determines intended use: | ||
18 | * | ||
19 | * <x>_r(void) : Returns the offset for register <x>. | ||
20 | * | ||
21 | * <x>_o(void) : Returns the offset for element <x>. | ||
22 | * | ||
23 | * <x>_w(void) : Returns the word offset for word (4 byte) element <x>. | ||
24 | * | ||
25 | * <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits. | ||
26 | * | ||
27 | * <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted | ||
28 | * and masked to place it at field <y> of register <x>. This value | ||
29 | * can be |'d with others to produce a full register value for | ||
30 | * register <x>. | ||
31 | * | ||
32 | * <x>_<y>_m(void) : Returns a mask for field <y> of register <x>. This | ||
33 | * value can be ~'d and then &'d to clear the value of field <y> for | ||
34 | * register <x>. | ||
35 | * | ||
36 | * <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted | ||
37 | * to place it at field <y> of register <x>. This value can be |'d | ||
38 | * with others to produce a full register value for <x>. | ||
39 | * | ||
40 | * <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register | ||
41 | * <x> value 'r' after being shifted to place its LSB at bit 0. | ||
42 | * This value is suitable for direct comparison with other unshifted | ||
43 | * values appropriate for use in field <y> of register <x>. | ||
44 | * | ||
45 | * <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for | ||
46 | * field <y> of register <x>. This value is suitable for direct | ||
47 | * comparison with unshifted values appropriate for use in field <y> | ||
48 | * of register <x>. | ||
49 | */ | ||
50 | #ifndef _hw_gc6_gp106_h_ | ||
51 | #define _hw_gc6_gp106_h_ | ||
52 | static inline u32 gc6_sci_strap_r(void) | ||
53 | { | ||
54 | return 0x00010ebb0; | ||
55 | } | ||
56 | #endif | ||
diff --git a/drivers/gpu/nvgpu/include/bios.h b/drivers/gpu/nvgpu/include/bios.h index 3af5bcf4..83d972e3 100644 --- a/drivers/gpu/nvgpu/include/bios.h +++ b/drivers/gpu/nvgpu/include/bios.h | |||
@@ -408,4 +408,98 @@ struct vfield_entry { | |||
408 | u16 strap_desc; | 408 | u16 strap_desc; |
409 | } __packed; | 409 | } __packed; |
410 | 410 | ||
411 | #define PERF_CLK_DOMAINS_IDX_MAX (32) | ||
412 | #define PERF_CLK_DOMAINS_IDX_INVALID PERF_CLK_DOMAINS_IDX_MAX | ||
413 | |||
414 | #define VBIOS_PSTATE_TABLE_VERSION_5X 0x50 | ||
415 | #define VBIOS_PSTATE_HEADER_5X_SIZE_10 (10) | ||
416 | |||
417 | struct vbios_pstate_header_5x { | ||
418 | u8 version; | ||
419 | u8 header_size; | ||
420 | u8 base_entry_size; | ||
421 | u8 base_entry_count; | ||
422 | u8 clock_entry_size; | ||
423 | u8 clock_entry_count; | ||
424 | u8 flags0; | ||
425 | u8 initial_pstate; | ||
426 | u8 cpi_support_level; | ||
427 | u8 cpi_features; | ||
428 | } __packed; | ||
429 | |||
430 | #define VBIOS_PSTATE_CLOCK_ENTRY_5X_SIZE_6 6 | ||
431 | |||
432 | #define VBIOS_PSTATE_BASE_ENTRY_5X_SIZE_2 0x2 | ||
433 | #define VBIOS_PSTATE_BASE_ENTRY_5X_SIZE_3 0x3 | ||
434 | |||
435 | struct vbios_pstate_entry_clock_5x { | ||
436 | u16 param0; | ||
437 | u32 param1; | ||
438 | } __packed; | ||
439 | |||
440 | struct vbios_pstate_entry_5x { | ||
441 | u8 pstate_level; | ||
442 | u8 flags0; | ||
443 | u8 lpwr_entry_idx; | ||
444 | struct vbios_pstate_entry_clock_5x clockEntry[PERF_CLK_DOMAINS_IDX_MAX]; | ||
445 | } __packed; | ||
446 | |||
447 | #define VBIOS_PSTATE_5X_CLOCK_PROG_PARAM0_NOM_FREQ_MHZ_SHIFT 0 | ||
448 | #define VBIOS_PSTATE_5X_CLOCK_PROG_PARAM0_NOM_FREQ_MHZ_MASK 0x00003FFF | ||
449 | |||
450 | #define VBIOS_PSTATE_5X_CLOCK_PROG_PARAM1_MIN_FREQ_MHZ_SHIFT 0 | ||
451 | #define VBIOS_PSTATE_5X_CLOCK_PROG_PARAM1_MIN_FREQ_MHZ_MASK 0x00003FFF | ||
452 | |||
453 | #define VBIOS_PSTATE_5X_CLOCK_PROG_PARAM1_MAX_FREQ_MHZ_SHIFT 14 | ||
454 | #define VBIOS_PSTATE_5X_CLOCK_PROG_PARAM1_MAX_FREQ_MHZ_MASK 0x0FFFC000 | ||
455 | |||
456 | #define VBIOS_PERFLEVEL_SKIP_ENTRY 0xFF | ||
457 | |||
458 | #define VBIOS_MEMORY_CLOCK_HEADER_11_VERSION 0x11 | ||
459 | |||
460 | #define VBIOS_MEMORY_CLOCK_HEADER_11_0_SIZE 16 | ||
461 | #define VBIOS_MEMORY_CLOCK_HEADER_11_1_SIZE 21 | ||
462 | #define VBIOS_MEMORY_CLOCK_HEADER_11_2_SIZE 26 | ||
463 | |||
464 | struct vbios_memory_clock_header_1x { | ||
465 | u8 version; | ||
466 | u8 header_size; | ||
467 | u8 base_entry_size; | ||
468 | u8 strap_entry_size; | ||
469 | u8 strap_entry_count; | ||
470 | u8 entry_count; | ||
471 | u8 flags; | ||
472 | u8 fbvdd_settle_time; | ||
473 | u32 cfg_pwrd_val; | ||
474 | u16 fbvddq_high; | ||
475 | u16 fbvddq_low; | ||
476 | u32 script_list_ptr; | ||
477 | u8 script_list_count; | ||
478 | u32 cmd_script_list_ptr; | ||
479 | u8 cmd_script_list_count; | ||
480 | } __packed; | ||
481 | |||
482 | #define VBIOS_MEMORY_CLOCK_BASE_ENTRY_11_2_SIZE 20 | ||
483 | |||
484 | struct vbios_memory_clock_base_entry_11 { | ||
485 | u16 minimum; | ||
486 | u16 maximum; | ||
487 | u32 script_pointer; | ||
488 | u8 flags0; | ||
489 | u32 fbpa_config; | ||
490 | u32 fbpa_config1; | ||
491 | u8 flags1; | ||
492 | u8 ref_mpllssf_freq_delta; | ||
493 | u8 flags2; | ||
494 | } __packed; | ||
495 | |||
496 | /* Script Pointer Index */ | ||
497 | /* #define VBIOS_MEMORY_CLOCK_BASE_ENTRY_11_FLAGS1_SCRIPT_INDEX 3:2*/ | ||
498 | #define VBIOS_MEMORY_CLOCK_BASE_ENTRY_11_FLAGS1_SCRIPT_INDEX_MASK 0xc | ||
499 | #define VBIOS_MEMORY_CLOCK_BASE_ENTRY_11_FLAGS1_SCRIPT_INDEX_SHIFT 2 | ||
500 | /* #define VBIOS_MEMORY_CLOCK_BASE_ENTRY_12_FLAGS2_CMD_SCRIPT_INDEX 1:0*/ | ||
501 | #define VBIOS_MEMORY_CLOCK_BASE_ENTRY_12_FLAGS2_CMD_SCRIPT_INDEX_MASK 0x3 | ||
502 | #define VBIOS_MEMORY_CLOCK_BASE_ENTRY_12_FLAGS2_CMD_SCRIPT_INDEX_SHIFT 0 | ||
503 | |||
411 | #endif | 504 | #endif |
505 | |||