summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gk20a/gr_ctx_gk20a.c
diff options
context:
space:
mode:
authorArto Merilainen <amerilainen@nvidia.com>2014-03-19 03:38:25 -0400
committerDan Willemsen <dwillemsen@nvidia.com>2015-03-18 15:08:53 -0400
commita9785995d5f22aaeb659285f8aeb64d8b56982e0 (patch)
treecc75f75bcf43db316a002a7a240b81f299bf6d7f /drivers/gpu/nvgpu/gk20a/gr_ctx_gk20a.c
parent61efaf843c22b85424036ec98015121c08f5f16c (diff)
gpu: nvgpu: Add NVIDIA GPU Driver
This patch moves the NVIDIA GPU driver to a new location. Bug 1482562 Change-Id: I24293810b9d0f1504fd9be00135e21dad656ccb6 Signed-off-by: Arto Merilainen <amerilainen@nvidia.com> Reviewed-on: http://git-master/r/383722 Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/gr_ctx_gk20a.c')
-rw-r--r--drivers/gpu/nvgpu/gk20a/gr_ctx_gk20a.c333
1 files changed, 333 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gr_ctx_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_ctx_gk20a.c
new file mode 100644
index 00000000..59404f1d
--- /dev/null
+++ b/drivers/gpu/nvgpu/gk20a/gr_ctx_gk20a.c
@@ -0,0 +1,333 @@
1/*
2 * drivers/video/tegra/host/gk20a/gr_ctx_gk20a.c
3 *
4 * GK20A Graphics Context
5 *
6 * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22#include <linux/firmware.h>
23
24#include "gk20a.h"
25#include "gr_ctx_gk20a.h"
26#include "hw_gr_gk20a.h"
27
28static int gr_gk20a_alloc_load_netlist_u32(u32 *src, u32 len,
29 struct u32_list_gk20a *u32_list)
30{
31 u32_list->count = (len + sizeof(u32) - 1) / sizeof(u32);
32 if (!alloc_u32_list_gk20a(u32_list))
33 return -ENOMEM;
34
35 memcpy(u32_list->l, src, len);
36
37 return 0;
38}
39
40static int gr_gk20a_alloc_load_netlist_av(u32 *src, u32 len,
41 struct av_list_gk20a *av_list)
42{
43 av_list->count = len / sizeof(struct av_gk20a);
44 if (!alloc_av_list_gk20a(av_list))
45 return -ENOMEM;
46
47 memcpy(av_list->l, src, len);
48
49 return 0;
50}
51
52static int gr_gk20a_alloc_load_netlist_aiv(u32 *src, u32 len,
53 struct aiv_list_gk20a *aiv_list)
54{
55 aiv_list->count = len / sizeof(struct aiv_gk20a);
56 if (!alloc_aiv_list_gk20a(aiv_list))
57 return -ENOMEM;
58
59 memcpy(aiv_list->l, src, len);
60
61 return 0;
62}
63
64static int gr_gk20a_get_netlist_name(int index, char *name)
65{
66 switch (index) {
67#ifdef GK20A_NETLIST_IMAGE_FW_NAME
68 case NETLIST_FINAL:
69 sprintf(name, GK20A_NETLIST_IMAGE_FW_NAME);
70 return 0;
71#endif
72#ifdef GK20A_NETLIST_IMAGE_A
73 case NETLIST_SLOT_A:
74 sprintf(name, GK20A_NETLIST_IMAGE_A);
75 return 0;
76#endif
77#ifdef GK20A_NETLIST_IMAGE_B
78 case NETLIST_SLOT_B:
79 sprintf(name, GK20A_NETLIST_IMAGE_B);
80 return 0;
81#endif
82#ifdef GK20A_NETLIST_IMAGE_C
83 case NETLIST_SLOT_C:
84 sprintf(name, GK20A_NETLIST_IMAGE_C);
85 return 0;
86#endif
87#ifdef GK20A_NETLIST_IMAGE_D
88 case NETLIST_SLOT_D:
89 sprintf(name, GK20A_NETLIST_IMAGE_D);
90 return 0;
91#endif
92 default:
93 return -1;
94 }
95
96 return -1;
97}
98
99static int gr_gk20a_init_ctx_vars_fw(struct gk20a *g, struct gr_gk20a *gr)
100{
101 struct device *d = dev_from_gk20a(g);
102 const struct firmware *netlist_fw;
103 struct netlist_image *netlist = NULL;
104 char name[MAX_NETLIST_NAME];
105 u32 i, major_v = ~0, major_v_hw, netlist_num;
106 int net, max, err = -ENOENT;
107
108 gk20a_dbg_fn("");
109
110#ifdef GK20A_NETLIST_IMAGE_FW_NAME
111 net = NETLIST_FINAL;
112 max = 0;
113 major_v_hw = ~0;
114 g->gr.ctx_vars.dynamic = false;
115#else
116 net = NETLIST_SLOT_A;
117 max = MAX_NETLIST;
118 major_v_hw = gk20a_readl(g, gr_fecs_ctx_state_store_major_rev_id_r());
119 g->gr.ctx_vars.dynamic = true;
120#endif
121
122 for (; net < max; net++) {
123
124 if (gr_gk20a_get_netlist_name(net, name) != 0) {
125 gk20a_warn(d, "invalid netlist index %d", net);
126 continue;
127 }
128
129 netlist_fw = gk20a_request_firmware(g, name);
130 if (!netlist_fw) {
131 gk20a_warn(d, "failed to load netlist %s", name);
132 continue;
133 }
134
135 netlist = (struct netlist_image *)netlist_fw->data;
136
137 for (i = 0; i < netlist->header.regions; i++) {
138 u32 *src = (u32 *)((u8 *)netlist + netlist->regions[i].data_offset);
139 u32 size = netlist->regions[i].data_size;
140
141 switch (netlist->regions[i].region_id) {
142 case NETLIST_REGIONID_FECS_UCODE_DATA:
143 gk20a_dbg_info("NETLIST_REGIONID_FECS_UCODE_DATA");
144 err = gr_gk20a_alloc_load_netlist_u32(
145 src, size, &g->gr.ctx_vars.ucode.fecs.data);
146 if (err)
147 goto clean_up;
148 break;
149 case NETLIST_REGIONID_FECS_UCODE_INST:
150 gk20a_dbg_info("NETLIST_REGIONID_FECS_UCODE_INST");
151 err = gr_gk20a_alloc_load_netlist_u32(
152 src, size, &g->gr.ctx_vars.ucode.fecs.inst);
153 if (err)
154 goto clean_up;
155 break;
156 case NETLIST_REGIONID_GPCCS_UCODE_DATA:
157 gk20a_dbg_info("NETLIST_REGIONID_GPCCS_UCODE_DATA");
158 err = gr_gk20a_alloc_load_netlist_u32(
159 src, size, &g->gr.ctx_vars.ucode.gpccs.data);
160 if (err)
161 goto clean_up;
162 break;
163 case NETLIST_REGIONID_GPCCS_UCODE_INST:
164 gk20a_dbg_info("NETLIST_REGIONID_GPCCS_UCODE_INST");
165 err = gr_gk20a_alloc_load_netlist_u32(
166 src, size, &g->gr.ctx_vars.ucode.gpccs.inst);
167 if (err)
168 goto clean_up;
169 break;
170 case NETLIST_REGIONID_SW_BUNDLE_INIT:
171 gk20a_dbg_info("NETLIST_REGIONID_SW_BUNDLE_INIT");
172 err = gr_gk20a_alloc_load_netlist_av(
173 src, size, &g->gr.ctx_vars.sw_bundle_init);
174 if (err)
175 goto clean_up;
176 break;
177 case NETLIST_REGIONID_SW_METHOD_INIT:
178 gk20a_dbg_info("NETLIST_REGIONID_SW_METHOD_INIT");
179 err = gr_gk20a_alloc_load_netlist_av(
180 src, size, &g->gr.ctx_vars.sw_method_init);
181 if (err)
182 goto clean_up;
183 break;
184 case NETLIST_REGIONID_SW_CTX_LOAD:
185 gk20a_dbg_info("NETLIST_REGIONID_SW_CTX_LOAD");
186 err = gr_gk20a_alloc_load_netlist_aiv(
187 src, size, &g->gr.ctx_vars.sw_ctx_load);
188 if (err)
189 goto clean_up;
190 break;
191 case NETLIST_REGIONID_SW_NON_CTX_LOAD:
192 gk20a_dbg_info("NETLIST_REGIONID_SW_NON_CTX_LOAD");
193 err = gr_gk20a_alloc_load_netlist_av(
194 src, size, &g->gr.ctx_vars.sw_non_ctx_load);
195 if (err)
196 goto clean_up;
197 break;
198 case NETLIST_REGIONID_CTXREG_SYS:
199 gk20a_dbg_info("NETLIST_REGIONID_CTXREG_SYS");
200 err = gr_gk20a_alloc_load_netlist_aiv(
201 src, size, &g->gr.ctx_vars.ctxsw_regs.sys);
202 if (err)
203 goto clean_up;
204 break;
205 case NETLIST_REGIONID_CTXREG_GPC:
206 gk20a_dbg_info("NETLIST_REGIONID_CTXREG_GPC");
207 err = gr_gk20a_alloc_load_netlist_aiv(
208 src, size, &g->gr.ctx_vars.ctxsw_regs.gpc);
209 if (err)
210 goto clean_up;
211 break;
212 case NETLIST_REGIONID_CTXREG_TPC:
213 gk20a_dbg_info("NETLIST_REGIONID_CTXREG_TPC");
214 err = gr_gk20a_alloc_load_netlist_aiv(
215 src, size, &g->gr.ctx_vars.ctxsw_regs.tpc);
216 if (err)
217 goto clean_up;
218 break;
219 case NETLIST_REGIONID_CTXREG_ZCULL_GPC:
220 gk20a_dbg_info("NETLIST_REGIONID_CTXREG_ZCULL_GPC");
221 err = gr_gk20a_alloc_load_netlist_aiv(
222 src, size, &g->gr.ctx_vars.ctxsw_regs.zcull_gpc);
223 if (err)
224 goto clean_up;
225 break;
226 case NETLIST_REGIONID_CTXREG_PPC:
227 gk20a_dbg_info("NETLIST_REGIONID_CTXREG_PPC");
228 err = gr_gk20a_alloc_load_netlist_aiv(
229 src, size, &g->gr.ctx_vars.ctxsw_regs.ppc);
230 if (err)
231 goto clean_up;
232 break;
233 case NETLIST_REGIONID_CTXREG_PM_SYS:
234 gk20a_dbg_info("NETLIST_REGIONID_CTXREG_PM_SYS");
235 err = gr_gk20a_alloc_load_netlist_aiv(
236 src, size, &g->gr.ctx_vars.ctxsw_regs.pm_sys);
237 if (err)
238 goto clean_up;
239 break;
240 case NETLIST_REGIONID_CTXREG_PM_GPC:
241 gk20a_dbg_info("NETLIST_REGIONID_CTXREG_PM_GPC");
242 err = gr_gk20a_alloc_load_netlist_aiv(
243 src, size, &g->gr.ctx_vars.ctxsw_regs.pm_gpc);
244 if (err)
245 goto clean_up;
246 break;
247 case NETLIST_REGIONID_CTXREG_PM_TPC:
248 gk20a_dbg_info("NETLIST_REGIONID_CTXREG_PM_TPC");
249 err = gr_gk20a_alloc_load_netlist_aiv(
250 src, size, &g->gr.ctx_vars.ctxsw_regs.pm_tpc);
251 if (err)
252 goto clean_up;
253 break;
254 case NETLIST_REGIONID_BUFFER_SIZE:
255 g->gr.ctx_vars.buffer_size = *src;
256 gk20a_dbg_info("NETLIST_REGIONID_BUFFER_SIZE : %d",
257 g->gr.ctx_vars.buffer_size);
258 break;
259 case NETLIST_REGIONID_CTXSW_REG_BASE_INDEX:
260 g->gr.ctx_vars.regs_base_index = *src;
261 gk20a_dbg_info("NETLIST_REGIONID_CTXSW_REG_BASE_INDEX : %d",
262 g->gr.ctx_vars.regs_base_index);
263 break;
264 case NETLIST_REGIONID_MAJORV:
265 major_v = *src;
266 gk20a_dbg_info("NETLIST_REGIONID_MAJORV : %d",
267 major_v);
268 break;
269 case NETLIST_REGIONID_NETLIST_NUM:
270 netlist_num = *src;
271 gk20a_dbg_info("NETLIST_REGIONID_NETLIST_NUM : %d",
272 netlist_num);
273 break;
274 case NETLIST_REGIONID_CTXREG_PMPPC:
275 gk20a_dbg_info("NETLIST_REGIONID_CTXREG_PMPPC skipped");
276 break;
277 default:
278 gk20a_warn(d, "unrecognized region %d skipped", i);
279 break;
280 }
281 }
282
283 if (net != NETLIST_FINAL && major_v != major_v_hw) {
284 gk20a_dbg_info("skip %s: major_v 0x%08x doesn't match hw 0x%08x",
285 name, major_v, major_v_hw);
286 goto clean_up;
287 }
288
289 g->gr.ctx_vars.valid = true;
290 g->gr.netlist = net;
291
292 release_firmware(netlist_fw);
293 gk20a_dbg_fn("done");
294 goto done;
295
296clean_up:
297 kfree(g->gr.ctx_vars.ucode.fecs.inst.l);
298 kfree(g->gr.ctx_vars.ucode.fecs.data.l);
299 kfree(g->gr.ctx_vars.ucode.gpccs.inst.l);
300 kfree(g->gr.ctx_vars.ucode.gpccs.data.l);
301 kfree(g->gr.ctx_vars.sw_bundle_init.l);
302 kfree(g->gr.ctx_vars.sw_method_init.l);
303 kfree(g->gr.ctx_vars.sw_ctx_load.l);
304 kfree(g->gr.ctx_vars.sw_non_ctx_load.l);
305 kfree(g->gr.ctx_vars.ctxsw_regs.sys.l);
306 kfree(g->gr.ctx_vars.ctxsw_regs.gpc.l);
307 kfree(g->gr.ctx_vars.ctxsw_regs.tpc.l);
308 kfree(g->gr.ctx_vars.ctxsw_regs.zcull_gpc.l);
309 kfree(g->gr.ctx_vars.ctxsw_regs.ppc.l);
310 kfree(g->gr.ctx_vars.ctxsw_regs.pm_sys.l);
311 kfree(g->gr.ctx_vars.ctxsw_regs.pm_gpc.l);
312 kfree(g->gr.ctx_vars.ctxsw_regs.pm_tpc.l);
313 release_firmware(netlist_fw);
314 err = -ENOENT;
315 }
316
317done:
318 if (g->gr.ctx_vars.valid) {
319 gk20a_dbg_info("netlist image %s loaded", name);
320 return 0;
321 } else {
322 gk20a_err(d, "failed to load netlist image!!");
323 return err;
324 }
325}
326
327int gr_gk20a_init_ctx_vars(struct gk20a *g, struct gr_gk20a *gr)
328{
329 if (tegra_platform_is_linsim())
330 return gr_gk20a_init_ctx_vars_sim(g, gr);
331 else
332 return gr_gk20a_init_ctx_vars_fw(g, gr);
333}