summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gm206/bios_gm206.c
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2016-03-23 11:43:53 -0400
committerTerje Bergstrom <tbergstrom@nvidia.com>2016-05-23 17:15:25 -0400
commitfb64e1f1b9c2162f521dfe3956655accb911d6a7 (patch)
tree15236c00323c8d24102f5a1221f1b313d62bfac2 /drivers/gpu/nvgpu/gm206/bios_gm206.c
parentc25e1da93e09a421b8c2b91df720d4bc603db378 (diff)
gpu: nvgpu: Add support for gm204 and gm206
Add support for chips gm204 and gm206. Adds also support for reading VBIOS and booting devinit and pre-os images on PMU. Change-Id: I4824b44245611e5379ace62793cc37158048f432 Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-on: http://git-master/r/1120467 GVS: Gerrit_Virtual_Submit Reviewed-by: Ken Adams <kadams@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gm206/bios_gm206.c')
-rw-r--r--drivers/gpu/nvgpu/gm206/bios_gm206.c718
1 files changed, 718 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gm206/bios_gm206.c b/drivers/gpu/nvgpu/gm206/bios_gm206.c
new file mode 100644
index 00000000..005507bc
--- /dev/null
+++ b/drivers/gpu/nvgpu/gm206/bios_gm206.c
@@ -0,0 +1,718 @@
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 <linux/delay.h>
15#include <linux/types.h>
16
17#include "gk20a/gk20a.h"
18#include "gm20b/fifo_gm20b.h"
19#include "fifo_gm206.h"
20#include "hw_pwr_gm206.h"
21#include "hw_mc_gm206.h"
22#include "hw_xve_gm206.h"
23#include "hw_top_gm206.h"
24
25#define BIT_HEADER_ID 0xb8ff
26#define BIT_HEADER_SIGNATURE 0x00544942
27#define BIOS_SIZE 0x40000
28#define NV_PCFG 0x88000
29#define PMU_BOOT_TIMEOUT_DEFAULT 100 /* usec */
30#define PMU_BOOT_TIMEOUT_MAX 2000000 /* usec */
31
32static u16 gm206_bios_rdu16(struct gk20a *g, int offset)
33{
34 u16 val = (g->bios.data[offset+1] << 8) + g->bios.data[offset];
35 return val;
36}
37
38static u32 gm206_bios_rdu32(struct gk20a *g, int offset)
39{
40 u32 val = (g->bios.data[offset+3] << 24) +
41 (g->bios.data[offset+2] << 16) +
42 (g->bios.data[offset+1] << 8) +
43 g->bios.data[offset];
44 return val;
45}
46
47struct bit {
48 u16 id;
49 u32 signature;
50 u16 bcd_version;
51 u8 header_size;
52 u8 token_size;
53 u8 token_entries;
54 u8 header_checksum;
55} __packed;
56
57struct bit_token {
58 u8 token_id;
59 u8 data_version;
60 u16 data_size;
61 u16 data_ptr;
62} __packed;
63
64#define TOKEN_ID_NVINIT_PTRS 0x49
65#define TOKEN_ID_FALCON_DATA 0x70
66
67struct nvinit_ptrs {
68 u16 initscript_table_ptr;
69 u16 macro_index_table_ptr;
70 u16 macro_table_ptr;
71 u16 condition_table_ptr;
72 u16 io_condition_table_ptr;
73 u16 io_flag_condition_table_ptr;
74 u16 init_function_table_ptr;
75 u16 vbios_private_table_ptr;
76 u16 data_arrays_table_ptr;
77 u16 pcie_settings_script_ptr;
78 u16 devinit_tables_ptr;
79 u16 devinit_tables_size;
80 u16 bootscripts_ptr;
81 u16 bootscripts_size;
82 u16 nvlink_config_data_ptr;
83} __packed;
84
85struct falcon_data_v2 {
86 u32 falcon_ucode_table_ptr;
87} __packed;
88
89struct falcon_ucode_table_hdr_v1 {
90 u8 version;
91 u8 header_size;
92 u8 entry_size;
93 u8 entry_count;
94 u8 desc_version;
95 u8 desc_size;
96} __packed;
97
98struct falcon_ucode_table_entry_v1 {
99 u8 application_id;
100 u8 target_id;
101 u32 desc_ptr;
102} __packed;
103
104#define TARGET_ID_PMU 0x01
105#define APPLICATION_ID_DEVINIT 0x04
106#define APPLICATION_ID_PRE_OS 0x01
107
108struct falcon_ucode_desc_v1 {
109 union {
110 u32 v_desc;
111 u32 stored_size;
112 } hdr_size;
113 u32 uncompressed_size;
114 u32 virtual_entry;
115 u32 interface_offset;
116 u32 imem_phys_base;
117 u32 imem_load_size;
118 u32 imem_virt_base;
119 u32 imem_sec_base;
120 u32 imem_sec_size;
121 u32 dmem_offset;
122 u32 dmem_phys_base;
123 u32 dmem_load_size;
124} __packed;
125
126struct application_interface_table_hdr_v1 {
127 u8 version;
128 u8 header_size;
129 u8 entry_size;
130 u8 entry_count;
131} __packed;
132
133struct application_interface_entry_v1 {
134 u32 id;
135 u32 dmem_offset;
136} __packed;
137
138#define APPINFO_ID_DEVINIT 0x01
139
140struct devinit_engine_interface {
141 u32 field0;
142 u32 field1;
143 u32 tables_phys_base;
144 u32 tables_virt_base;
145 u32 script_phys_base;
146 u32 script_virt_base;
147 u32 script_virt_entry;
148 u16 script_size;
149 u8 memory_strap_count;
150 u8 reserved;
151 u32 memory_information_table_virt_base;
152 u32 empty_script_virt_base;
153 u32 cond_table_virt_base;
154 u32 io_cond_table_virt_base;
155 u32 data_arrays_table_virt_base;
156 u32 gpio_assignment_table_virt_base;
157} __packed;
158
159struct pci_exp_rom {
160 u16 sig;
161 u8 reserved[0x16];
162 u16 pci_data_struct_ptr;
163 u32 size_of_block;
164} __packed;
165
166struct pci_data_struct {
167 u32 sig;
168 u16 vendor_id;
169 u16 device_id;
170 u16 device_list_ptr;
171 u16 pci_data_struct_len;
172 u8 pci_data_struct_rev;
173 u8 class_code[3];
174 u16 image_len;
175 u16 vendor_rom_rev;
176 u8 code_type;
177 u8 last_image;
178 u16 max_runtime_image_len;
179} __packed;
180
181struct pci_ext_data_struct {
182 u32 sig;
183 u16 nv_pci_data_ext_rev;
184 u16 nv_pci_data_ext_len;
185 u16 sub_image_len;
186 u8 priv_last_image;
187 u8 flags;
188} __packed;
189
190static void gm206_bios_parse_rom(struct gk20a *g)
191{
192 int offset = 0;
193 int last = 0;
194
195 while (!last) {
196 struct pci_exp_rom *pci_rom;
197 struct pci_data_struct *pci_data;
198 struct pci_ext_data_struct *pci_ext_data;
199
200 pci_rom = (struct pci_exp_rom *)&g->bios.data[offset];
201 gk20a_dbg_fn("pci rom sig %04x ptr %04x block %x",
202 pci_rom->sig, pci_rom->pci_data_struct_ptr,
203 pci_rom->size_of_block);
204
205 pci_data =
206 (struct pci_data_struct *)
207 &g->bios.data[offset + pci_rom->pci_data_struct_ptr];
208 gk20a_dbg_fn("pci data sig %08x len %d image len %x type %x last %d max %08x",
209 pci_data->sig, pci_data->pci_data_struct_len,
210 pci_data->image_len, pci_data->code_type,
211 pci_data->last_image,
212 pci_data->max_runtime_image_len);
213
214 if (pci_data->code_type == 0x3) {
215 pci_ext_data = (struct pci_ext_data_struct *)
216 &g->bios.data[(offset +
217 pci_rom->pci_data_struct_ptr +
218 pci_data->pci_data_struct_len +
219 0xf)
220 & ~0xf];
221 gk20a_dbg_fn("pci ext data sig %08x rev %x len %x sub_image_len %x priv_last %d flags %x",
222 pci_ext_data->sig,
223 pci_ext_data->nv_pci_data_ext_rev,
224 pci_ext_data->nv_pci_data_ext_len,
225 pci_ext_data->sub_image_len,
226 pci_ext_data->priv_last_image,
227 pci_ext_data->flags);
228
229 gk20a_dbg_fn("expansion rom offset %x",
230 pci_data->image_len * 512);
231 g->bios.expansion_rom_offset =
232 pci_data->image_len * 512;
233 offset += pci_ext_data->sub_image_len * 512;
234 last = pci_ext_data->priv_last_image;
235 } else {
236 offset += pci_data->image_len * 512;
237 last = pci_data->last_image;
238 }
239 }
240}
241
242static void gm206_bios_parse_nvinit_ptrs(struct gk20a *g, int offset)
243{
244 struct nvinit_ptrs nvinit_ptrs;
245
246 memcpy(&nvinit_ptrs, &g->bios.data[offset], sizeof(nvinit_ptrs));
247 gk20a_dbg_fn("devinit ptr %x size %d", nvinit_ptrs.devinit_tables_ptr,
248 nvinit_ptrs.devinit_tables_size);
249 gk20a_dbg_fn("bootscripts ptr %x size %d", nvinit_ptrs.bootscripts_ptr,
250 nvinit_ptrs.bootscripts_size);
251
252 g->bios.devinit_tables = &g->bios.data[nvinit_ptrs.devinit_tables_ptr];
253 g->bios.devinit_tables_size = nvinit_ptrs.devinit_tables_size;
254 g->bios.bootscripts = &g->bios.data[nvinit_ptrs.bootscripts_ptr];
255 g->bios.bootscripts_size = nvinit_ptrs.bootscripts_size;
256}
257
258static void gm206_bios_parse_devinit_appinfo(struct gk20a *g, int dmem_offset)
259{
260 struct devinit_engine_interface interface;
261
262 memcpy(&interface, &g->bios.devinit.dmem[dmem_offset], sizeof(interface));
263 gk20a_dbg_fn("devinit tables phys %x script phys %x size %d",
264 interface.tables_phys_base,
265 interface.script_phys_base,
266 interface.script_size);
267
268 g->bios.devinit_tables_phys_base = interface.tables_phys_base;
269 g->bios.devinit_script_phys_base = interface.script_phys_base;
270}
271
272static int gm206_bios_parse_appinfo_table(struct gk20a *g, int offset)
273{
274 struct application_interface_table_hdr_v1 hdr;
275 int i;
276
277 memcpy(&hdr, &g->bios.data[offset], sizeof(hdr));
278
279 gk20a_dbg_fn("appInfoHdr ver %d size %d entrySize %d entryCount %d",
280 hdr.version, hdr.header_size,
281 hdr.entry_size, hdr.entry_count);
282
283 if (hdr.version != 1)
284 return 0;
285
286 offset += sizeof(hdr);
287 for (i = 0; i < hdr.entry_count; i++) {
288 struct application_interface_entry_v1 entry;
289
290 memcpy(&entry, &g->bios.data[offset], sizeof(entry));
291
292 gk20a_dbg_fn("appInfo id %d dmem_offset %d",
293 entry.id, entry.dmem_offset);
294
295 if (entry.id == APPINFO_ID_DEVINIT)
296 gm206_bios_parse_devinit_appinfo(g, entry.dmem_offset);
297
298 offset += hdr.entry_size;
299 }
300
301 return 0;
302}
303
304static int gm206_bios_parse_falcon_ucode_desc(struct gk20a *g,
305 struct nvgpu_bios_ucode *ucode, int offset)
306{
307 struct falcon_ucode_desc_v1 desc;
308
309 memcpy(&desc, &g->bios.data[offset], sizeof(desc));
310 gk20a_dbg_info("falcon ucode desc stored size %d uncompressed size %d",
311 desc.hdr_size.stored_size, desc.uncompressed_size);
312 gk20a_dbg_info("falcon ucode desc virtualEntry %x, interfaceOffset %x",
313 desc.virtual_entry, desc.interface_offset);
314 gk20a_dbg_info("falcon ucode IMEM phys base %x, load size %x virt base %x sec base %x sec size %x",
315 desc.imem_phys_base, desc.imem_load_size,
316 desc.imem_virt_base, desc.imem_sec_base,
317 desc.imem_sec_size);
318 gk20a_dbg_info("falcon ucode DMEM offset %d phys base %x, load size %d",
319 desc.dmem_offset, desc.dmem_phys_base,
320 desc.dmem_load_size);
321
322 if (desc.hdr_size.stored_size != desc.uncompressed_size) {
323 gk20a_dbg_info("does not match");
324 return -EINVAL;
325 }
326
327 ucode->code_entry_point = desc.virtual_entry;
328 ucode->bootloader = &g->bios.data[offset] + sizeof(desc);
329 ucode->bootloader_phys_base = desc.imem_phys_base;
330 ucode->bootloader_size = desc.imem_load_size - desc.imem_sec_size;
331 ucode->ucode = ucode->bootloader + ucode->bootloader_size;
332 ucode->phys_base = ucode->bootloader_phys_base + ucode->bootloader_size;
333 ucode->size = desc.imem_sec_size;
334 ucode->dmem = ucode->bootloader + desc.dmem_offset;
335 ucode->dmem_phys_base = desc.dmem_phys_base;
336 ucode->dmem_size = desc.dmem_load_size;
337
338 return gm206_bios_parse_appinfo_table(g,
339 offset + sizeof(desc) +
340 desc.dmem_offset + desc.interface_offset);
341}
342
343static int gm206_bios_parse_falcon_ucode_table(struct gk20a *g, int offset)
344{
345 struct falcon_ucode_table_hdr_v1 hdr;
346 int i;
347
348 memcpy(&hdr, &g->bios.data[offset], sizeof(hdr));
349 gk20a_dbg_fn("falcon ucode table ver %d size %d entrySize %d entryCount %d descVer %d descSize %d",
350 hdr.version, hdr.header_size,
351 hdr.entry_size, hdr.entry_count,
352 hdr.desc_version, hdr.desc_size);
353
354 if (hdr.version != 1)
355 return -EINVAL;
356
357 offset += hdr.header_size;
358
359 for (i = 0; i < hdr.entry_count; i++) {
360 struct falcon_ucode_table_entry_v1 entry;
361
362 memcpy(&entry, &g->bios.data[offset], sizeof(entry));
363
364 gk20a_dbg_fn("falcon ucode table entry appid %x targetId %x descPtr %x",
365 entry.application_id, entry.target_id,
366 entry.desc_ptr);
367
368 if (entry.target_id == TARGET_ID_PMU &&
369 entry.application_id == APPLICATION_ID_DEVINIT) {
370 int err;
371
372 err = gm206_bios_parse_falcon_ucode_desc(g,
373 &g->bios.devinit, entry.desc_ptr);
374 if (err)
375 err = gm206_bios_parse_falcon_ucode_desc(g,
376 &g->bios.devinit,
377 entry.desc_ptr +
378 g->bios.expansion_rom_offset);
379
380 if (err)
381 gk20a_err(dev_from_gk20a(g),
382 "could not parse devinit ucode desc");
383 } else if (entry.target_id == TARGET_ID_PMU &&
384 entry.application_id == APPLICATION_ID_PRE_OS) {
385 int err;
386
387 err = gm206_bios_parse_falcon_ucode_desc(g,
388 &g->bios.preos, entry.desc_ptr);
389 if (err)
390 err = gm206_bios_parse_falcon_ucode_desc(g,
391 &g->bios.preos,
392 entry.desc_ptr +
393 g->bios.expansion_rom_offset);
394
395 if (err)
396 gk20a_err(dev_from_gk20a(g),
397 "could not parse preos ucode desc");
398 }
399
400 offset += hdr.entry_size;
401 }
402
403 return 0;
404}
405
406static void gm206_bios_parse_falcon_data_v2(struct gk20a *g, int offset)
407{
408 struct falcon_data_v2 falcon_data;
409 int err;
410
411 memcpy(&falcon_data, &g->bios.data[offset], sizeof(falcon_data));
412 gk20a_dbg_fn("falcon ucode table ptr %x",
413 falcon_data.falcon_ucode_table_ptr);
414 err = gm206_bios_parse_falcon_ucode_table(g,
415 falcon_data.falcon_ucode_table_ptr);
416 if (err)
417 err = gm206_bios_parse_falcon_ucode_table(g,
418 falcon_data.falcon_ucode_table_ptr +
419 g->bios.expansion_rom_offset);
420
421 if (err)
422 gk20a_err(dev_from_gk20a(g),
423 "could not parse falcon ucode table");
424}
425
426static void gm206_bios_parse_bit(struct gk20a *g, int offset)
427{
428 struct bit bit;
429 struct bit_token bit_token;
430 int i;
431
432 gk20a_dbg_fn("");
433 memcpy(&bit, &g->bios.data[offset], sizeof(bit));
434
435 gk20a_dbg_info("BIT header: %04x %08x", bit.id, bit.signature);
436 gk20a_dbg_info("tokens: %d entries * %d bytes",
437 bit.token_entries, bit.token_size);
438
439 offset += bit.header_size;
440 for (i = 0; i < bit.token_entries; i++) {
441 memcpy(&bit_token, &g->bios.data[offset], sizeof(bit_token));
442
443 gk20a_dbg_info("BIT token id %d ptr %d size %d ver %d",
444 bit_token.token_id, bit_token.data_ptr,
445 bit_token.data_size, bit_token.data_version);
446
447 switch (bit_token.token_id) {
448 case TOKEN_ID_NVINIT_PTRS:
449 gm206_bios_parse_nvinit_ptrs(g, bit_token.data_ptr);
450 break;
451 case TOKEN_ID_FALCON_DATA:
452 if (bit_token.data_version == 2)
453 gm206_bios_parse_falcon_data_v2(g,
454 bit_token.data_ptr);
455 break;
456 default:
457 break;
458 }
459
460 offset += bit.token_size;
461 }
462 gk20a_dbg_fn("done");
463}
464
465static void upload_code(struct gk20a *g, u32 dst,
466 u8 *src, u32 size, u8 port, bool sec)
467{
468 u32 i, words;
469 u32 *src_u32 = (u32 *)src;
470 u32 blk;
471 u32 tag = 0;
472
473 gk20a_dbg_info("upload %d bytes to %x", size, dst);
474
475 words = size >> 2;
476
477 blk = dst >> 8;
478 tag = blk;
479
480 gk20a_dbg_info("upload %d words to %x block %d",
481 words, dst, blk);
482
483 gk20a_writel(g, pwr_falcon_imemc_r(port),
484 pwr_falcon_imemc_offs_f(dst >> 2) |
485 pwr_falcon_imemc_blk_f(blk) |
486 pwr_falcon_imemc_aincw_f(1) |
487 sec << 28);
488
489 for (i = 0; i < words; i++) {
490 if (i % 64 == 0) {
491 gk20a_writel(g, 0x10a188, tag);
492 tag++;
493 }
494
495 gk20a_writel(g, pwr_falcon_imemd_r(port), src_u32[i]);
496 }
497
498 while (i % 64) {
499 gk20a_writel(g, pwr_falcon_imemd_r(port), 0);
500 i++;
501 }
502}
503
504static void upload_data(struct gk20a *g, u32 dst, u8 *src, u32 size, u8 port)
505{
506 u32 i, words;
507 u32 *src_u32 = (u32 *)src;
508 u32 blk;
509
510 gk20a_dbg_info("upload %d bytes to %x", size, dst);
511
512 words = DIV_ROUND_UP(size, 4);
513
514 blk = dst >> 8;
515
516 gk20a_dbg_info("upload %d words to %x blk %d",
517 words, dst, blk);
518 gk20a_writel(g, pwr_falcon_dmemc_r(port),
519 pwr_falcon_dmemc_offs_f(dst >> 2) |
520 pwr_falcon_dmemc_blk_f(blk) |
521 pwr_falcon_dmemc_aincw_f(1));
522
523 for (i = 0; i < words; i++)
524 gk20a_writel(g, pwr_falcon_dmemd_r(port), src_u32[i]);
525}
526
527static int gm206_bios_devinit(struct gk20a *g)
528{
529 int retries = PMU_BOOT_TIMEOUT_MAX / PMU_BOOT_TIMEOUT_DEFAULT;
530 int err = 0;
531 int val;
532
533 gk20a_dbg_fn("");
534 g->ops.pmu.reset(g);
535
536 do {
537 u32 w = gk20a_readl(g, pwr_falcon_dmactl_r()) &
538 (pwr_falcon_dmactl_dmem_scrubbing_m() |
539 pwr_falcon_dmactl_imem_scrubbing_m());
540
541 if (!w) {
542 gk20a_dbg_fn("done");
543 break;
544 }
545 udelay(PMU_BOOT_TIMEOUT_DEFAULT);
546 } while (--retries || !tegra_platform_is_silicon());
547
548 /* todo check retries */
549 upload_code(g, g->bios.devinit.bootloader_phys_base,
550 g->bios.devinit.bootloader,
551 g->bios.devinit.bootloader_size,
552 0, 0);
553 upload_code(g, g->bios.devinit.phys_base,
554 g->bios.devinit.ucode,
555 g->bios.devinit.size,
556 0, 1);
557 upload_data(g, g->bios.devinit.dmem_phys_base,
558 g->bios.devinit.dmem,
559 g->bios.devinit.dmem_size,
560 0);
561 upload_data(g, g->bios.devinit_tables_phys_base,
562 g->bios.devinit_tables,
563 g->bios.devinit_tables_size,
564 0);
565 upload_data(g, g->bios.devinit_script_phys_base,
566 g->bios.bootscripts,
567 g->bios.bootscripts_size,
568 0);
569
570 gk20a_writel(g, pwr_falcon_bootvec_r(),
571 pwr_falcon_bootvec_vec_f(g->bios.devinit.code_entry_point));
572 gk20a_writel(g, pwr_falcon_dmactl_r(),
573 pwr_falcon_dmactl_require_ctx_f(0));
574 gk20a_writel(g, pwr_falcon_cpuctl_r(),
575 pwr_falcon_cpuctl_startcpu_f(1));
576
577 retries = PMU_BOOT_TIMEOUT_MAX / PMU_BOOT_TIMEOUT_DEFAULT;
578 do {
579 val = top_scratch1_devinit_completed_v(
580 gk20a_readl(g, top_scratch1_r()));
581 udelay(PMU_BOOT_TIMEOUT_DEFAULT);
582 } while (!val && retries--);
583
584 gk20a_writel(g, pwr_falcon_irqsclr_r(),
585 pwr_falcon_irqstat_halt_true_f());
586 gk20a_readl(g, pwr_falcon_irqsclr_r());
587
588 if (!retries)
589 err = -EINVAL;
590
591 gk20a_dbg_fn("done");
592 return err;
593}
594
595static int gm206_bios_preos(struct gk20a *g)
596{
597 int retries = GR_IDLE_CHECK_MAX / GR_IDLE_CHECK_DEFAULT;
598 int err = 0;
599 int val;
600
601 gk20a_dbg_fn("");
602 g->ops.pmu.reset(g);
603
604 do {
605 u32 w = gk20a_readl(g, pwr_falcon_dmactl_r()) &
606 (pwr_falcon_dmactl_dmem_scrubbing_m() |
607 pwr_falcon_dmactl_imem_scrubbing_m());
608
609 if (!w) {
610 gk20a_dbg_fn("done");
611 break;
612 }
613 udelay(GR_IDLE_CHECK_DEFAULT);
614 } while (--retries || !tegra_platform_is_silicon());
615
616 /* todo check retries */
617 upload_code(g, g->bios.preos.bootloader_phys_base,
618 g->bios.preos.bootloader,
619 g->bios.preos.bootloader_size,
620 0, 0);
621 upload_code(g, g->bios.preos.phys_base,
622 g->bios.preos.ucode,
623 g->bios.preos.size,
624 0, 1);
625 upload_data(g, g->bios.preos.dmem_phys_base,
626 g->bios.preos.dmem,
627 g->bios.preos.dmem_size,
628 0);
629
630 gk20a_writel(g, pwr_falcon_bootvec_r(),
631 pwr_falcon_bootvec_vec_f(g->bios.preos.code_entry_point));
632 gk20a_writel(g, pwr_falcon_dmactl_r(),
633 pwr_falcon_dmactl_require_ctx_f(0));
634 gk20a_writel(g, pwr_falcon_cpuctl_r(),
635 pwr_falcon_cpuctl_startcpu_f(1));
636
637 retries = PMU_BOOT_TIMEOUT_MAX / PMU_BOOT_TIMEOUT_DEFAULT;
638 do {
639 val = pwr_falcon_cpuctl_halt_intr_v(
640 gk20a_readl(g, pwr_falcon_cpuctl_r()));
641 udelay(PMU_BOOT_TIMEOUT_DEFAULT);
642 } while (!val && retries--);
643
644 gk20a_writel(g, pwr_falcon_irqsclr_r(),
645 pwr_falcon_irqstat_halt_true_f());
646 gk20a_readl(g, pwr_falcon_irqsclr_r());
647
648 if (!retries)
649 err = -EINVAL;
650
651 gk20a_dbg_fn("done");
652 return err;
653}
654
655static int gm206_bios_init(struct gk20a *g)
656{
657 int i;
658 struct gk20a_platform *platform = dev_get_drvdata(g->dev);
659 struct dentry *d;
660 int err;
661
662 gk20a_dbg_fn("");
663 g->bios.data = kzalloc(BIOS_SIZE, GFP_KERNEL);
664 if (!g->bios.data)
665 return -ENOMEM;
666
667 gk20a_dbg_info("reading bios");
668 gk20a_writel(g, NV_PCFG + xve_rom_ctrl_r(),
669 xve_rom_ctrl_rom_shadow_disabled_f());
670 for (i = 0; i < BIOS_SIZE/4; i++) {
671 u32 val = be32_to_cpu(gk20a_readl(g, 0x300000 + i*4));
672
673 g->bios.data[(i*4)] = (val >> 24) & 0xff;
674 g->bios.data[(i*4)+1] = (val >> 16) & 0xff;
675 g->bios.data[(i*4)+2] = (val >> 8) & 0xff;
676 g->bios.data[(i*4)+3] = val & 0xff;
677 }
678 gk20a_writel(g, NV_PCFG + xve_rom_ctrl_r(),
679 xve_rom_ctrl_rom_shadow_enabled_f());
680
681 gm206_bios_parse_rom(g);
682 gk20a_dbg_info("read bios");
683 for (i = 0; i < BIOS_SIZE; i++) {
684 if (gm206_bios_rdu16(g, i) == BIT_HEADER_ID &&
685 gm206_bios_rdu32(g, i+2) == BIT_HEADER_SIGNATURE) {
686 gm206_bios_parse_bit(g, i);
687 }
688 }
689
690 g->bios_blob.data = g->bios.data;
691 g->bios_blob.size = BIOS_SIZE;
692
693 d = debugfs_create_blob("bios", S_IRUGO, platform->debugfs,
694 &g->bios_blob);
695 if (!d)
696 gk20a_err(g->dev, "No debugfs?");
697
698 gk20a_dbg_fn("done");
699
700 err = gm206_bios_devinit(g);
701 if (err) {
702 gk20a_err(g->dev, "devinit failed");
703 return err;
704 }
705
706 err = gm206_bios_preos(g);
707 if (err) {
708 gk20a_err(g->dev, "pre-os failed");
709 return err;
710 }
711
712 return 0;
713}
714
715void gm206_init_bios(struct gpu_ops *gops)
716{
717 gops->bios.init = gm206_bios_init;
718}