summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gm206
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2017-02-09 11:17:47 -0500
committermobile promotions <svcmobile_promotions@nvidia.com>2017-02-17 16:46:32 -0500
commit53465def649b813987ca0d4a7ced744305204b82 (patch)
treecdff16681cb0442de3b1a8bd151b2a38c0bc5311 /drivers/gpu/nvgpu/gm206
parent29a79e6b80c6a0da489d8b0a470c86e2fec9c355 (diff)
gpu: nvgpu: Generalize BIOS code
Most of BIOS parsing code is not specific to any particular GPU. Move most of the code to generic files, and leave only chip specific parts dealing with microcontroller boot into chip specific files. As most of the parsing is generic, they do not need to be called via HALs so remove the HALs and change the calls into direct function calls. All definitions meant to be used outside BIOS code itself are now in <nvgpu/bios.h> Change-Id: Id48e94c74511d6e95645e90e5bba5c12ef8da45d Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-on: http://git-master/r/1302222 GVS: Gerrit_Virtual_Submit
Diffstat (limited to 'drivers/gpu/nvgpu/gm206')
-rw-r--r--drivers/gpu/nvgpu/gm206/bios_gm206.c635
-rw-r--r--drivers/gpu/nvgpu/gm206/bios_gm206.h56
-rw-r--r--drivers/gpu/nvgpu/gm206/hal_gm206.c2
3 files changed, 12 insertions, 681 deletions
diff --git a/drivers/gpu/nvgpu/gm206/bios_gm206.c b/drivers/gpu/nvgpu/gm206/bios_gm206.c
index a5551f42..3d12b9ac 100644
--- a/drivers/gpu/nvgpu/gm206/bios_gm206.c
+++ b/drivers/gpu/nvgpu/gm206/bios_gm206.c
@@ -16,6 +16,8 @@
16#include <linux/firmware.h> 16#include <linux/firmware.h>
17#include <linux/pci.h> 17#include <linux/pci.h>
18 18
19#include <nvgpu/bios.h>
20
19#include "gk20a/gk20a.h" 21#include "gk20a/gk20a.h"
20#include "gm20b/fifo_gm20b.h" 22#include "gm20b/fifo_gm20b.h"
21#include "fifo_gm206.h" 23#include "fifo_gm206.h"
@@ -27,617 +29,12 @@
27#include <nvgpu/hw/gm206/hw_mc_gm206.h> 29#include <nvgpu/hw/gm206/hw_mc_gm206.h>
28#include <nvgpu/hw/gm206/hw_top_gm206.h> 30#include <nvgpu/hw/gm206/hw_top_gm206.h>
29 31
30#define BIT_HEADER_ID 0xb8ff
31#define BIT_HEADER_SIGNATURE 0x00544942
32#define BIOS_SIZE 0x40000
33#define PCI_EXP_ROM_SIG 0xaa55
34#define PCI_EXP_ROM_SIG_NV 0x4e56
35#define ROM_FILE_PAYLOAD_OFFSET 0xa00
36#define PMU_BOOT_TIMEOUT_DEFAULT 100 /* usec */ 32#define PMU_BOOT_TIMEOUT_DEFAULT 100 /* usec */
37#define PMU_BOOT_TIMEOUT_MAX 2000000 /* usec */ 33#define PMU_BOOT_TIMEOUT_MAX 2000000 /* usec */
38#define BIOS_OVERLAY_NAME "bios-%04x.rom" 34#define BIOS_OVERLAY_NAME "bios-%04x.rom"
39#define BIOS_OVERLAY_NAME_FORMATTED "bios-xxxx.rom" 35#define BIOS_OVERLAY_NAME_FORMATTED "bios-xxxx.rom"
40 36#define ROM_FILE_PAYLOAD_OFFSET 0xa00
41static u16 gm206_bios_rdu16(struct gk20a *g, int offset) 37#define BIOS_SIZE 0x40000
42{
43 u16 val = (g->bios.data[offset+1] << 8) + g->bios.data[offset];
44 return val;
45}
46
47static u32 gm206_bios_rdu32(struct gk20a *g, int offset)
48{
49 u32 val = (g->bios.data[offset+3] << 24) +
50 (g->bios.data[offset+2] << 16) +
51 (g->bios.data[offset+1] << 8) +
52 g->bios.data[offset];
53 return val;
54}
55
56struct bit {
57 u16 id;
58 u32 signature;
59 u16 bcd_version;
60 u8 header_size;
61 u8 token_size;
62 u8 token_entries;
63 u8 header_checksum;
64} __packed;
65
66#define TOKEN_ID_BIOSDATA 0x42
67#define TOKEN_ID_NVINIT_PTRS 0x49
68#define TOKEN_ID_FALCON_DATA 0x70
69#define TOKEN_ID_PERF_PTRS 0x50
70#define TOKEN_ID_CLOCK_PTRS 0x43
71#define TOKEN_ID_VIRT_PTRS 0x56
72#define TOKEN_ID_MEMORY_PTRS 0x4D
73
74
75union memory_ptrs {
76 struct {
77 u8 rsvd0[2];
78 u8 mem_strap_data_count;
79 u16 mem_strap_xlat_tbl_ptr;
80 u8 rsvd1[8];
81 } v1 __packed;
82 struct {
83 u8 mem_strap_data_count;
84 u16 mem_strap_xlat_tbl_ptr;
85 u8 rsvd[14];
86 } v2 __packed;
87};
88
89struct biosdata {
90 u32 version;
91 u8 oem_version;
92 u8 checksum;
93 u16 int15callbackspost;
94 u16 int16callbackssystem;
95 u16 boardid;
96 u16 framecount;
97 u8 biosmoddate[8];
98} __packed;
99
100struct nvinit_ptrs {
101 u16 initscript_table_ptr;
102 u16 macro_index_table_ptr;
103 u16 macro_table_ptr;
104 u16 condition_table_ptr;
105 u16 io_condition_table_ptr;
106 u16 io_flag_condition_table_ptr;
107 u16 init_function_table_ptr;
108 u16 vbios_private_table_ptr;
109 u16 data_arrays_table_ptr;
110 u16 pcie_settings_script_ptr;
111 u16 devinit_tables_ptr;
112 u16 devinit_tables_size;
113 u16 bootscripts_ptr;
114 u16 bootscripts_size;
115 u16 nvlink_config_data_ptr;
116} __packed;
117
118struct falcon_data_v2 {
119 u32 falcon_ucode_table_ptr;
120} __packed;
121
122struct falcon_ucode_table_hdr_v1 {
123 u8 version;
124 u8 header_size;
125 u8 entry_size;
126 u8 entry_count;
127 u8 desc_version;
128 u8 desc_size;
129} __packed;
130
131struct falcon_ucode_table_entry_v1 {
132 u8 application_id;
133 u8 target_id;
134 u32 desc_ptr;
135} __packed;
136
137#define TARGET_ID_PMU 0x01
138#define APPLICATION_ID_DEVINIT 0x04
139#define APPLICATION_ID_PRE_OS 0x01
140
141struct falcon_ucode_desc_v1 {
142 union {
143 u32 v_desc;
144 u32 stored_size;
145 } hdr_size;
146 u32 uncompressed_size;
147 u32 virtual_entry;
148 u32 interface_offset;
149 u32 imem_phys_base;
150 u32 imem_load_size;
151 u32 imem_virt_base;
152 u32 imem_sec_base;
153 u32 imem_sec_size;
154 u32 dmem_offset;
155 u32 dmem_phys_base;
156 u32 dmem_load_size;
157} __packed;
158
159struct application_interface_table_hdr_v1 {
160 u8 version;
161 u8 header_size;
162 u8 entry_size;
163 u8 entry_count;
164} __packed;
165
166struct application_interface_entry_v1 {
167 u32 id;
168 u32 dmem_offset;
169} __packed;
170
171#define APPINFO_ID_DEVINIT 0x01
172
173struct devinit_engine_interface {
174 u32 field0;
175 u32 field1;
176 u32 tables_phys_base;
177 u32 tables_virt_base;
178 u32 script_phys_base;
179 u32 script_virt_base;
180 u32 script_virt_entry;
181 u16 script_size;
182 u8 memory_strap_count;
183 u8 reserved;
184 u32 memory_information_table_virt_base;
185 u32 empty_script_virt_base;
186 u32 cond_table_virt_base;
187 u32 io_cond_table_virt_base;
188 u32 data_arrays_table_virt_base;
189 u32 gpio_assignment_table_virt_base;
190} __packed;
191
192struct pci_exp_rom {
193 u16 sig;
194 u8 reserved[0x16];
195 u16 pci_data_struct_ptr;
196 u32 size_of_block;
197} __packed;
198
199struct pci_data_struct {
200 u32 sig;
201 u16 vendor_id;
202 u16 device_id;
203 u16 device_list_ptr;
204 u16 pci_data_struct_len;
205 u8 pci_data_struct_rev;
206 u8 class_code[3];
207 u16 image_len;
208 u16 vendor_rom_rev;
209 u8 code_type;
210 u8 last_image;
211 u16 max_runtime_image_len;
212} __packed;
213
214struct pci_ext_data_struct {
215 u32 sig;
216 u16 nv_pci_data_ext_rev;
217 u16 nv_pci_data_ext_len;
218 u16 sub_image_len;
219 u8 priv_last_image;
220 u8 flags;
221} __packed;
222
223static int gm206_bios_parse_rom(struct gk20a *g)
224{
225 int offset = 0;
226 int last = 0;
227
228 while (!last) {
229 struct pci_exp_rom *pci_rom;
230 struct pci_data_struct *pci_data;
231 struct pci_ext_data_struct *pci_ext_data;
232
233 pci_rom = (struct pci_exp_rom *)&g->bios.data[offset];
234 gk20a_dbg_fn("pci rom sig %04x ptr %04x block %x",
235 pci_rom->sig, pci_rom->pci_data_struct_ptr,
236 pci_rom->size_of_block);
237
238 if (pci_rom->sig != PCI_EXP_ROM_SIG &&
239 pci_rom->sig != PCI_EXP_ROM_SIG_NV) {
240 gk20a_err(g->dev, "invalid VBIOS signature");
241 return -EINVAL;
242 }
243
244 pci_data =
245 (struct pci_data_struct *)
246 &g->bios.data[offset + pci_rom->pci_data_struct_ptr];
247 gk20a_dbg_fn("pci data sig %08x len %d image len %x type %x last %d max %08x",
248 pci_data->sig, pci_data->pci_data_struct_len,
249 pci_data->image_len, pci_data->code_type,
250 pci_data->last_image,
251 pci_data->max_runtime_image_len);
252
253 if (pci_data->code_type == 0x3) {
254 pci_ext_data = (struct pci_ext_data_struct *)
255 &g->bios.data[(offset +
256 pci_rom->pci_data_struct_ptr +
257 pci_data->pci_data_struct_len +
258 0xf)
259 & ~0xf];
260 gk20a_dbg_fn("pci ext data sig %08x rev %x len %x sub_image_len %x priv_last %d flags %x",
261 pci_ext_data->sig,
262 pci_ext_data->nv_pci_data_ext_rev,
263 pci_ext_data->nv_pci_data_ext_len,
264 pci_ext_data->sub_image_len,
265 pci_ext_data->priv_last_image,
266 pci_ext_data->flags);
267
268 gk20a_dbg_fn("expansion rom offset %x",
269 pci_data->image_len * 512);
270 g->bios.expansion_rom_offset =
271 pci_data->image_len * 512;
272 offset += pci_ext_data->sub_image_len * 512;
273 last = pci_ext_data->priv_last_image;
274 } else {
275 offset += pci_data->image_len * 512;
276 last = pci_data->last_image;
277 }
278 }
279
280 return 0;
281}
282
283static void gm206_bios_parse_biosdata(struct gk20a *g, int offset)
284{
285 struct biosdata biosdata;
286
287 memcpy(&biosdata, &g->bios.data[offset], sizeof(biosdata));
288 gk20a_dbg_fn("bios version %x, oem version %x",
289 biosdata.version,
290 biosdata.oem_version);
291
292 g->gpu_characteristics.vbios_version = biosdata.version;
293 g->gpu_characteristics.vbios_oem_version = biosdata.oem_version;
294}
295
296static void gm206_bios_parse_nvinit_ptrs(struct gk20a *g, int offset)
297{
298 struct nvinit_ptrs nvinit_ptrs;
299
300 memcpy(&nvinit_ptrs, &g->bios.data[offset], sizeof(nvinit_ptrs));
301 gk20a_dbg_fn("devinit ptr %x size %d", nvinit_ptrs.devinit_tables_ptr,
302 nvinit_ptrs.devinit_tables_size);
303 gk20a_dbg_fn("bootscripts ptr %x size %d", nvinit_ptrs.bootscripts_ptr,
304 nvinit_ptrs.bootscripts_size);
305
306 g->bios.devinit_tables = &g->bios.data[nvinit_ptrs.devinit_tables_ptr];
307 g->bios.devinit_tables_size = nvinit_ptrs.devinit_tables_size;
308 g->bios.bootscripts = &g->bios.data[nvinit_ptrs.bootscripts_ptr];
309 g->bios.bootscripts_size = nvinit_ptrs.bootscripts_size;
310 g->bios.condition_table_ptr = nvinit_ptrs.condition_table_ptr;
311}
312
313static void gm206_bios_parse_memory_ptrs(struct gk20a *g, int offset, u8 version)
314{
315 union memory_ptrs memory_ptrs;
316
317 if ((version < 1) || (version > 2))
318 return;
319
320 memcpy(&memory_ptrs, &g->bios.data[offset], sizeof(memory_ptrs));
321
322 g->bios.mem_strap_data_count = (version > 1) ? memory_ptrs.v2.mem_strap_data_count :
323 memory_ptrs.v1.mem_strap_data_count;
324 g->bios.mem_strap_xlat_tbl_ptr = (version > 1) ? memory_ptrs.v2.mem_strap_xlat_tbl_ptr :
325 memory_ptrs.v1.mem_strap_xlat_tbl_ptr;
326}
327
328static void gm206_bios_parse_devinit_appinfo(struct gk20a *g, int dmem_offset)
329{
330 struct devinit_engine_interface interface;
331
332 memcpy(&interface, &g->bios.devinit.dmem[dmem_offset], sizeof(interface));
333 gk20a_dbg_fn("devinit tables phys %x script phys %x size %d",
334 interface.tables_phys_base,
335 interface.script_phys_base,
336 interface.script_size);
337
338 g->bios.devinit_tables_phys_base = interface.tables_phys_base;
339 g->bios.devinit_script_phys_base = interface.script_phys_base;
340}
341
342static int gm206_bios_parse_appinfo_table(struct gk20a *g, int offset)
343{
344 struct application_interface_table_hdr_v1 hdr;
345 int i;
346
347 memcpy(&hdr, &g->bios.data[offset], sizeof(hdr));
348
349 gk20a_dbg_fn("appInfoHdr ver %d size %d entrySize %d entryCount %d",
350 hdr.version, hdr.header_size,
351 hdr.entry_size, hdr.entry_count);
352
353 if (hdr.version != 1)
354 return 0;
355
356 offset += sizeof(hdr);
357 for (i = 0; i < hdr.entry_count; i++) {
358 struct application_interface_entry_v1 entry;
359
360 memcpy(&entry, &g->bios.data[offset], sizeof(entry));
361
362 gk20a_dbg_fn("appInfo id %d dmem_offset %d",
363 entry.id, entry.dmem_offset);
364
365 if (entry.id == APPINFO_ID_DEVINIT)
366 gm206_bios_parse_devinit_appinfo(g, entry.dmem_offset);
367
368 offset += hdr.entry_size;
369 }
370
371 return 0;
372}
373
374static int gm206_bios_parse_falcon_ucode_desc(struct gk20a *g,
375 struct nvgpu_bios_ucode *ucode, int offset)
376{
377 struct falcon_ucode_desc_v1 desc;
378
379 memcpy(&desc, &g->bios.data[offset], sizeof(desc));
380 gk20a_dbg_info("falcon ucode desc stored size %d uncompressed size %d",
381 desc.hdr_size.stored_size, desc.uncompressed_size);
382 gk20a_dbg_info("falcon ucode desc virtualEntry %x, interfaceOffset %x",
383 desc.virtual_entry, desc.interface_offset);
384 gk20a_dbg_info("falcon ucode IMEM phys base %x, load size %x virt base %x sec base %x sec size %x",
385 desc.imem_phys_base, desc.imem_load_size,
386 desc.imem_virt_base, desc.imem_sec_base,
387 desc.imem_sec_size);
388 gk20a_dbg_info("falcon ucode DMEM offset %d phys base %x, load size %d",
389 desc.dmem_offset, desc.dmem_phys_base,
390 desc.dmem_load_size);
391
392 if (desc.hdr_size.stored_size != desc.uncompressed_size) {
393 gk20a_dbg_info("does not match");
394 return -EINVAL;
395 }
396
397 ucode->code_entry_point = desc.virtual_entry;
398 ucode->bootloader = &g->bios.data[offset] + sizeof(desc);
399 ucode->bootloader_phys_base = desc.imem_phys_base;
400 ucode->bootloader_size = desc.imem_load_size - desc.imem_sec_size;
401 ucode->ucode = ucode->bootloader + ucode->bootloader_size;
402 ucode->phys_base = ucode->bootloader_phys_base + ucode->bootloader_size;
403 ucode->size = desc.imem_sec_size;
404 ucode->dmem = ucode->bootloader + desc.dmem_offset;
405 ucode->dmem_phys_base = desc.dmem_phys_base;
406 ucode->dmem_size = desc.dmem_load_size;
407
408 return gm206_bios_parse_appinfo_table(g,
409 offset + sizeof(desc) +
410 desc.dmem_offset + desc.interface_offset);
411}
412
413static int gm206_bios_parse_falcon_ucode_table(struct gk20a *g, int offset)
414{
415 struct falcon_ucode_table_hdr_v1 hdr;
416 int i;
417
418 memcpy(&hdr, &g->bios.data[offset], sizeof(hdr));
419 gk20a_dbg_fn("falcon ucode table ver %d size %d entrySize %d entryCount %d descVer %d descSize %d",
420 hdr.version, hdr.header_size,
421 hdr.entry_size, hdr.entry_count,
422 hdr.desc_version, hdr.desc_size);
423
424 if (hdr.version != 1)
425 return -EINVAL;
426
427 offset += hdr.header_size;
428
429 for (i = 0; i < hdr.entry_count; i++) {
430 struct falcon_ucode_table_entry_v1 entry;
431
432 memcpy(&entry, &g->bios.data[offset], sizeof(entry));
433
434 gk20a_dbg_fn("falcon ucode table entry appid %x targetId %x descPtr %x",
435 entry.application_id, entry.target_id,
436 entry.desc_ptr);
437
438 if (entry.target_id == TARGET_ID_PMU &&
439 entry.application_id == APPLICATION_ID_DEVINIT) {
440 int err;
441
442 err = gm206_bios_parse_falcon_ucode_desc(g,
443 &g->bios.devinit, entry.desc_ptr);
444 if (err)
445 err = gm206_bios_parse_falcon_ucode_desc(g,
446 &g->bios.devinit,
447 entry.desc_ptr +
448 g->bios.expansion_rom_offset);
449
450 if (err)
451 gk20a_err(dev_from_gk20a(g),
452 "could not parse devinit ucode desc");
453 } else if (entry.target_id == TARGET_ID_PMU &&
454 entry.application_id == APPLICATION_ID_PRE_OS) {
455 int err;
456
457 err = gm206_bios_parse_falcon_ucode_desc(g,
458 &g->bios.preos, entry.desc_ptr);
459 if (err)
460 err = gm206_bios_parse_falcon_ucode_desc(g,
461 &g->bios.preos,
462 entry.desc_ptr +
463 g->bios.expansion_rom_offset);
464
465 if (err)
466 gk20a_err(dev_from_gk20a(g),
467 "could not parse preos ucode desc");
468 }
469
470 offset += hdr.entry_size;
471 }
472
473 return 0;
474}
475
476static void gm206_bios_parse_falcon_data_v2(struct gk20a *g, int offset)
477{
478 struct falcon_data_v2 falcon_data;
479 int err;
480
481 memcpy(&falcon_data, &g->bios.data[offset], sizeof(falcon_data));
482 gk20a_dbg_fn("falcon ucode table ptr %x",
483 falcon_data.falcon_ucode_table_ptr);
484 err = gm206_bios_parse_falcon_ucode_table(g,
485 falcon_data.falcon_ucode_table_ptr);
486 if (err)
487 err = gm206_bios_parse_falcon_ucode_table(g,
488 falcon_data.falcon_ucode_table_ptr +
489 g->bios.expansion_rom_offset);
490
491 if (err)
492 gk20a_err(dev_from_gk20a(g),
493 "could not parse falcon ucode table");
494}
495
496static void *gm206_bios_get_perf_table_ptrs(struct gk20a *g,
497 struct bit_token *ptoken, u8 table_id)
498{
499 u32 perf_table_id_offset = 0;
500 u8 *perf_table_ptr = NULL;
501 u8 data_size = 4;
502
503 if (ptoken != NULL) {
504
505 if (ptoken->token_id == TOKEN_ID_VIRT_PTRS) {
506 perf_table_id_offset = *((u16 *)&g->bios.data[
507 ptoken->data_ptr +
508 (table_id * PERF_PTRS_WIDTH_16)]);
509 data_size = PERF_PTRS_WIDTH_16;
510 } else {
511 perf_table_id_offset = *((u32 *)&g->bios.data[
512 ptoken->data_ptr +
513 (table_id * PERF_PTRS_WIDTH)]);
514 data_size = PERF_PTRS_WIDTH;
515 }
516 } else
517 return (void *)perf_table_ptr;
518
519 if (table_id < (ptoken->data_size/data_size)) {
520
521 gk20a_dbg_info("Perf_Tbl_ID-offset 0x%x Tbl_ID_Ptr-offset- 0x%x",
522 (ptoken->data_ptr +
523 (table_id * data_size)),
524 perf_table_id_offset);
525
526 if (perf_table_id_offset != 0) {
527 /* check is perf_table_id_offset is > 64k */
528 if (perf_table_id_offset & ~0xFFFF)
529 perf_table_ptr =
530 &g->bios.data[g->bios.expansion_rom_offset +
531 perf_table_id_offset];
532 else
533 perf_table_ptr =
534 &g->bios.data[perf_table_id_offset];
535 } else
536 gk20a_warn(g->dev, "PERF TABLE ID %d is NULL",
537 table_id);
538 } else
539 gk20a_warn(g->dev, "INVALID PERF TABLE ID - %d ", table_id);
540
541 return (void *)perf_table_ptr;
542}
543
544static void gm206_bios_parse_bit(struct gk20a *g, int offset)
545{
546 struct bit bit;
547 struct bit_token bit_token;
548 int i;
549
550 gk20a_dbg_fn("");
551 memcpy(&bit, &g->bios.data[offset], sizeof(bit));
552
553 gk20a_dbg_info("BIT header: %04x %08x", bit.id, bit.signature);
554 gk20a_dbg_info("tokens: %d entries * %d bytes",
555 bit.token_entries, bit.token_size);
556
557 offset += bit.header_size;
558 for (i = 0; i < bit.token_entries; i++) {
559 memcpy(&bit_token, &g->bios.data[offset], sizeof(bit_token));
560
561 gk20a_dbg_info("BIT token id %d ptr %d size %d ver %d",
562 bit_token.token_id, bit_token.data_ptr,
563 bit_token.data_size, bit_token.data_version);
564
565 switch (bit_token.token_id) {
566 case TOKEN_ID_BIOSDATA:
567 gm206_bios_parse_biosdata(g, bit_token.data_ptr);
568 break;
569 case TOKEN_ID_NVINIT_PTRS:
570 gm206_bios_parse_nvinit_ptrs(g, bit_token.data_ptr);
571 break;
572 case TOKEN_ID_FALCON_DATA:
573 if (bit_token.data_version == 2)
574 gm206_bios_parse_falcon_data_v2(g,
575 bit_token.data_ptr);
576 break;
577 case TOKEN_ID_PERF_PTRS:
578 g->bios.perf_token =
579 (struct bit_token *)&g->bios.data[offset];
580 break;
581 case TOKEN_ID_CLOCK_PTRS:
582 g->bios.clock_token =
583 (struct bit_token *)&g->bios.data[offset];
584 break;
585 case TOKEN_ID_VIRT_PTRS:
586 g->bios.virt_token =
587 (struct bit_token *)&g->bios.data[offset];
588 break;
589 case TOKEN_ID_MEMORY_PTRS:
590 gm206_bios_parse_memory_ptrs(g, bit_token.data_ptr,
591 bit_token.data_version);
592 default:
593 break;
594 }
595
596 offset += bit.token_size;
597 }
598 gk20a_dbg_fn("done");
599}
600
601static u32 __gm206_bios_readbyte(struct gk20a *g, u32 offset)
602{
603 return (u32) g->bios.data[offset];
604}
605
606u8 gm206_bios_read_u8(struct gk20a *g, u32 offset)
607{
608 return (u8) __gm206_bios_readbyte(g, offset);
609}
610
611s8 gm206_bios_read_s8(struct gk20a *g, u32 offset)
612{
613 u32 val;
614 val = __gm206_bios_readbyte(g, offset);
615 val = val & 0x80 ? (val | ~0xff) : val;
616
617 return (s8) val;
618}
619
620u16 gm206_bios_read_u16(struct gk20a *g, u32 offset)
621{
622 u16 val;
623
624 val = __gm206_bios_readbyte(g, offset) |
625 (__gm206_bios_readbyte(g, offset+1) << 8);
626
627 return val;
628}
629
630u32 gm206_bios_read_u32(struct gk20a *g, u32 offset)
631{
632 u32 val;
633
634 val = __gm206_bios_readbyte(g, offset) |
635 (__gm206_bios_readbyte(g, offset+1) << 8) |
636 (__gm206_bios_readbyte(g, offset+2) << 16) |
637 (__gm206_bios_readbyte(g, offset+3) << 24);
638
639 return val;
640}
641 38
642static void upload_code(struct gk20a *g, u32 dst, 39static void upload_code(struct gk20a *g, u32 dst,
643 u8 *src, u32 size, u8 port, bool sec) 40 u8 *src, u32 size, u8 port, bool sec)
@@ -831,14 +228,13 @@ static int gm206_bios_preos(struct gk20a *g)
831 return err; 228 return err;
832} 229}
833 230
834static int gm206_bios_init(struct gk20a *g) 231int gm206_bios_init(struct gk20a *g)
835{ 232{
836 unsigned int i; 233 unsigned int i;
837 struct gk20a_platform *platform = dev_get_drvdata(g->dev); 234 struct gk20a_platform *platform = dev_get_drvdata(g->dev);
838 struct dentry *d; 235 struct dentry *d;
839 const struct firmware *bios_fw; 236 const struct firmware *bios_fw;
840 int err; 237 int err;
841 bool found = 0;
842 struct pci_dev *pdev = to_pci_dev(g->dev); 238 struct pci_dev *pdev = to_pci_dev(g->dev);
843 char rom_name[sizeof(BIOS_OVERLAY_NAME_FORMATTED)]; 239 char rom_name[sizeof(BIOS_OVERLAY_NAME_FORMATTED)];
844 240
@@ -880,24 +276,10 @@ static int gm206_bios_init(struct gk20a *g)
880 g->ops.xve.enable_shadow_rom(g); 276 g->ops.xve.enable_shadow_rom(g);
881 } 277 }
882 278
883 err = gm206_bios_parse_rom(g); 279 err = nvgpu_bios_parse_rom(g);
884 if (err) 280 if (err)
885 return err; 281 return err;
886 282
887 gk20a_dbg_info("read bios");
888 for (i = 0; i < g->bios.size - 6; i++) {
889 if (gm206_bios_rdu16(g, i) == BIT_HEADER_ID &&
890 gm206_bios_rdu32(g, i+2) == BIT_HEADER_SIGNATURE) {
891 gm206_bios_parse_bit(g, i);
892 found = true;
893 }
894 }
895
896 if (!found) {
897 gk20a_err(g->dev, "no valid VBIOS found");
898 return -EINVAL;
899 }
900
901 if (g->gpu_characteristics.vbios_version < 283 if (g->gpu_characteristics.vbios_version <
902 platform->vbios_min_version) { 284 platform->vbios_min_version) {
903 gk20a_err(g->dev, "unsupported VBIOS version %08x", 285 gk20a_err(g->dev, "unsupported VBIOS version %08x",
@@ -936,8 +318,7 @@ free_firmware:
936 return err; 318 return err;
937} 319}
938 320
939void gm206_init_bios(struct gpu_ops *gops) 321void gm206_init_bios_ops(struct gpu_ops *gops)
940{ 322{
941 gops->bios.init = gm206_bios_init; 323 gops->bios_init = gm206_bios_init;
942 gops->bios.get_perf_table_ptrs = gm206_bios_get_perf_table_ptrs;
943} 324}
diff --git a/drivers/gpu/nvgpu/gm206/bios_gm206.h b/drivers/gpu/nvgpu/gm206/bios_gm206.h
index 6fe19fb0..090c7d24 100644
--- a/drivers/gpu/nvgpu/gm206/bios_gm206.h
+++ b/drivers/gpu/nvgpu/gm206/bios_gm206.h
@@ -14,60 +14,10 @@
14#ifndef NVGPU_BIOS_GM206_H 14#ifndef NVGPU_BIOS_GM206_H
15#define NVGPU_BIOS_GM206_H 15#define NVGPU_BIOS_GM206_H
16 16
17#define PERF_PTRS_WIDTH 0x4 17struct gk20a;
18#define PERF_PTRS_WIDTH_16 0x2
19
20#define NV_PCFG 0x88000
21
22enum {
23 CLOCKS_TABLE = 2,
24 CLOCK_PROGRAMMING_TABLE,
25 FLL_TABLE,
26 VIN_TABLE,
27 FREQUENCY_CONTROLLER_TABLE
28};
29
30enum {
31 PERFORMANCE_TABLE = 0,
32 MEMORY_CLOCK_TABLE,
33 MEMORY_TWEAK_TABLE,
34 POWER_CONTROL_TABLE,
35 THERMAL_CONTROL_TABLE,
36 THERMAL_DEVICE_TABLE,
37 THERMAL_COOLERS_TABLE,
38 PERFORMANCE_SETTINGS_SCRIPT,
39 CONTINUOUS_VIRTUAL_BINNING_TABLE,
40 POWER_SENSORS_TABLE = 0xA,
41 POWER_CAPPING_TABLE = 0xB,
42 POWER_TOPOLOGY_TABLE = 0xF,
43 THERMAL_CHANNEL_TABLE = 0x12,
44 VOLTAGE_RAIL_TABLE = 26,
45 VOLTAGE_DEVICE_TABLE,
46 VOLTAGE_POLICY_TABLE,
47 LOWPOWER_TABLE,
48 LOWPOWER_GR_TABLE = 32,
49 LOWPOWER_MS_TABLE = 33,
50};
51
52enum {
53 VP_FIELD_TABLE = 0,
54 VP_FIELD_REGISTER,
55 VP_TRANSLATION_TABLE,
56};
57
58struct bit_token {
59 u8 token_id;
60 u8 data_version;
61 u16 data_size;
62 u16 data_ptr;
63} __packed;
64
65struct gpu_ops; 18struct gpu_ops;
66 19
67void gm206_init_bios(struct gpu_ops *gops); 20int gm206_bios_init(struct gk20a *g);
68u8 gm206_bios_read_u8(struct gk20a *g, u32 offset); 21void gm206_init_bios_ops(struct gpu_ops *gops);
69s8 gm206_bios_read_s8(struct gk20a *g, u32 offset);
70u16 gm206_bios_read_u16(struct gk20a *g, u32 offset);
71u32 gm206_bios_read_u32(struct gk20a *g, u32 offset);
72 22
73#endif 23#endif
diff --git a/drivers/gpu/nvgpu/gm206/hal_gm206.c b/drivers/gpu/nvgpu/gm206/hal_gm206.c
index 8ad5a397..e2b84d81 100644
--- a/drivers/gpu/nvgpu/gm206/hal_gm206.c
+++ b/drivers/gpu/nvgpu/gm206/hal_gm206.c
@@ -198,7 +198,7 @@ int gm206_init_hal(struct gk20a *g)
198#if defined(CONFIG_GK20A_CYCLE_STATS) 198#if defined(CONFIG_GK20A_CYCLE_STATS)
199 gk20a_init_css_ops(gops); 199 gk20a_init_css_ops(gops);
200#endif 200#endif
201 gm206_init_bios(gops); 201 gm206_init_bios_ops(gops);
202 switch(ver){ 202 switch(ver){
203 case GK20A_GPUID_GM206: 203 case GK20A_GPUID_GM206:
204 gops->name = "gm206"; 204 gops->name = "gm206";