diff options
author | Arto Merilainen <amerilainen@nvidia.com> | 2014-03-19 03:38:25 -0400 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2015-03-18 15:08:53 -0400 |
commit | a9785995d5f22aaeb659285f8aeb64d8b56982e0 (patch) | |
tree | cc75f75bcf43db316a002a7a240b81f299bf6d7f /drivers/gpu/nvgpu/gk20a/gr_ctx_gk20a.c | |
parent | 61efaf843c22b85424036ec98015121c08f5f16c (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.c | 333 |
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 | |||
28 | static 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 | |||
40 | static 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 | |||
52 | static 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 | |||
64 | static 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 | |||
99 | static 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 | |||
296 | clean_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 | |||
317 | done: | ||
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 | |||
327 | int 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 | } | ||