diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/gv11b/pmu_gv11b.c | 121 |
1 files changed, 120 insertions, 1 deletions
diff --git a/drivers/gpu/nvgpu/gv11b/pmu_gv11b.c b/drivers/gpu/nvgpu/gv11b/pmu_gv11b.c index 62e42c31..e235e39b 100644 --- a/drivers/gpu/nvgpu/gv11b/pmu_gv11b.c +++ b/drivers/gpu/nvgpu/gv11b/pmu_gv11b.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * GV11B PMU | 2 | * GV11B PMU |
3 | * | 3 | * |
4 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. | 4 | * Copyright (c) 2016-2017, NVIDIA CORPORATION. All rights reserved. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
@@ -15,19 +15,138 @@ | |||
15 | 15 | ||
16 | #include <linux/delay.h> /* for udelay */ | 16 | #include <linux/delay.h> /* for udelay */ |
17 | #include <linux/tegra-fuse.h> | 17 | #include <linux/tegra-fuse.h> |
18 | #include <linux/clk.h> | ||
18 | #include "gk20a/gk20a.h" | 19 | #include "gk20a/gk20a.h" |
19 | #include "gp10b/pmu_gp10b.h" | 20 | #include "gp10b/pmu_gp10b.h" |
20 | 21 | ||
21 | #include "pmu_gv11b.h" | 22 | #include "pmu_gv11b.h" |
22 | #include "hw_pwr_gv11b.h" | 23 | #include "hw_pwr_gv11b.h" |
23 | 24 | ||
25 | #define ALIGN_4KB 12 | ||
26 | |||
24 | static bool gv11b_is_pmu_supported(struct gk20a *g) | 27 | static bool gv11b_is_pmu_supported(struct gk20a *g) |
25 | { | 28 | { |
26 | return false; | 29 | return false; |
27 | } | 30 | } |
28 | 31 | ||
32 | static int gv11b_pmu_bootstrap(struct pmu_gk20a *pmu) | ||
33 | { | ||
34 | struct gk20a *g = gk20a_from_pmu(pmu); | ||
35 | struct gk20a_platform *platform = dev_get_drvdata(g->dev); | ||
36 | struct mm_gk20a *mm = &g->mm; | ||
37 | struct pmu_ucode_desc *desc = pmu->desc; | ||
38 | u64 addr_code_lo, addr_data_lo, addr_load_lo; | ||
39 | u64 addr_code_hi, addr_data_hi, addr_load_hi; | ||
40 | u32 i, blocks, addr_args; | ||
41 | |||
42 | gk20a_dbg_fn(""); | ||
43 | |||
44 | gk20a_writel(g, pwr_falcon_itfen_r(), | ||
45 | gk20a_readl(g, pwr_falcon_itfen_r()) | | ||
46 | pwr_falcon_itfen_ctxen_enable_f()); | ||
47 | |||
48 | gk20a_writel(g, pwr_pmu_new_instblk_r(), | ||
49 | pwr_pmu_new_instblk_ptr_f( | ||
50 | gk20a_mm_inst_block_addr(g, &mm->pmu.inst_block) >> ALIGN_4KB) | ||
51 | | pwr_pmu_new_instblk_valid_f(1) | ||
52 | | pwr_pmu_new_instblk_target_sys_ncoh_f()); | ||
53 | |||
54 | /* TBD: load all other surfaces */ | ||
55 | g->ops.pmu_ver.set_pmu_cmdline_args_trace_size( | ||
56 | pmu, GK20A_PMU_TRACE_BUFSIZE); | ||
57 | g->ops.pmu_ver.set_pmu_cmdline_args_trace_dma_base(pmu); | ||
58 | g->ops.pmu_ver.set_pmu_cmdline_args_trace_dma_idx( | ||
59 | pmu, GK20A_PMU_DMAIDX_VIRT); | ||
60 | |||
61 | g->ops.pmu_ver.set_pmu_cmdline_args_cpu_freq(pmu, | ||
62 | clk_get_rate(platform->clk[1])); | ||
63 | |||
64 | addr_args = (pwr_falcon_hwcfg_dmem_size_v( | ||
65 | gk20a_readl(g, pwr_falcon_hwcfg_r())) | ||
66 | << GK20A_PMU_DMEM_BLKSIZE2) - | ||
67 | g->ops.pmu_ver.get_pmu_cmdline_args_size(pmu); | ||
68 | |||
69 | pmu_copy_to_dmem(pmu, addr_args, | ||
70 | (u8 *)(g->ops.pmu_ver.get_pmu_cmdline_args_ptr(pmu)), | ||
71 | g->ops.pmu_ver.get_pmu_cmdline_args_size(pmu), 0); | ||
72 | |||
73 | gk20a_writel(g, pwr_falcon_dmemc_r(0), | ||
74 | pwr_falcon_dmemc_offs_f(0) | | ||
75 | pwr_falcon_dmemc_blk_f(0) | | ||
76 | pwr_falcon_dmemc_aincw_f(1)); | ||
77 | |||
78 | addr_code_lo = u64_lo32((pmu->ucode.gpu_va + | ||
79 | desc->app_start_offset + | ||
80 | desc->app_resident_code_offset) >> 8); | ||
81 | |||
82 | addr_code_hi = u64_hi32((pmu->ucode.gpu_va + | ||
83 | desc->app_start_offset + | ||
84 | desc->app_resident_code_offset) >> 8); | ||
85 | addr_data_lo = u64_lo32((pmu->ucode.gpu_va + | ||
86 | desc->app_start_offset + | ||
87 | desc->app_resident_data_offset) >> 8); | ||
88 | addr_data_hi = u64_hi32((pmu->ucode.gpu_va + | ||
89 | desc->app_start_offset + | ||
90 | desc->app_resident_data_offset) >> 8); | ||
91 | addr_load_lo = u64_lo32((pmu->ucode.gpu_va + | ||
92 | desc->bootloader_start_offset) >> 8); | ||
93 | addr_load_hi = u64_hi32((pmu->ucode.gpu_va + | ||
94 | desc->bootloader_start_offset) >> 8); | ||
95 | |||
96 | gk20a_writel(g, pwr_falcon_dmemd_r(0), 0x0); | ||
97 | gk20a_writel(g, pwr_falcon_dmemd_r(0), 0x0); | ||
98 | gk20a_writel(g, pwr_falcon_dmemd_r(0), 0x0); | ||
99 | gk20a_writel(g, pwr_falcon_dmemd_r(0), 0x0); | ||
100 | gk20a_writel(g, pwr_falcon_dmemd_r(0), 0x0); | ||
101 | gk20a_writel(g, pwr_falcon_dmemd_r(0), 0x0); | ||
102 | gk20a_writel(g, pwr_falcon_dmemd_r(0), 0x0); | ||
103 | gk20a_writel(g, pwr_falcon_dmemd_r(0), 0x0); | ||
104 | gk20a_writel(g, pwr_falcon_dmemd_r(0), GK20A_PMU_DMAIDX_UCODE); | ||
105 | gk20a_writel(g, pwr_falcon_dmemd_r(0), addr_code_lo << 8); | ||
106 | gk20a_writel(g, pwr_falcon_dmemd_r(0), addr_code_hi); | ||
107 | gk20a_writel(g, pwr_falcon_dmemd_r(0), desc->app_resident_code_offset); | ||
108 | gk20a_writel(g, pwr_falcon_dmemd_r(0), desc->app_resident_code_size); | ||
109 | gk20a_writel(g, pwr_falcon_dmemd_r(0), 0x0); | ||
110 | gk20a_writel(g, pwr_falcon_dmemd_r(0), 0x0); | ||
111 | gk20a_writel(g, pwr_falcon_dmemd_r(0), desc->app_imem_entry); | ||
112 | gk20a_writel(g, pwr_falcon_dmemd_r(0), addr_data_lo << 8); | ||
113 | gk20a_writel(g, pwr_falcon_dmemd_r(0), addr_data_hi); | ||
114 | gk20a_writel(g, pwr_falcon_dmemd_r(0), desc->app_resident_data_size); | ||
115 | gk20a_writel(g, pwr_falcon_dmemd_r(0), 0x1); | ||
116 | gk20a_writel(g, pwr_falcon_dmemd_r(0), addr_args); | ||
117 | |||
118 | g->ops.pmu.write_dmatrfbase(g, | ||
119 | addr_load_lo - (desc->bootloader_imem_offset >> 8)); | ||
120 | |||
121 | blocks = ((desc->bootloader_size + 0xFF) & ~0xFF) >> 8; | ||
122 | |||
123 | for (i = 0; i < blocks; i++) { | ||
124 | gk20a_writel(g, pwr_falcon_dmatrfmoffs_r(), | ||
125 | desc->bootloader_imem_offset + (i << 8)); | ||
126 | gk20a_writel(g, pwr_falcon_dmatrffboffs_r(), | ||
127 | desc->bootloader_imem_offset + (i << 8)); | ||
128 | gk20a_writel(g, pwr_falcon_dmatrfcmd_r(), | ||
129 | pwr_falcon_dmatrfcmd_imem_f(1) | | ||
130 | pwr_falcon_dmatrfcmd_write_f(0) | | ||
131 | pwr_falcon_dmatrfcmd_size_f(6) | | ||
132 | pwr_falcon_dmatrfcmd_ctxdma_f(GK20A_PMU_DMAIDX_UCODE)); | ||
133 | } | ||
134 | |||
135 | gk20a_writel(g, pwr_falcon_bootvec_r(), | ||
136 | pwr_falcon_bootvec_vec_f(desc->bootloader_entry_point)); | ||
137 | |||
138 | gk20a_writel(g, pwr_falcon_cpuctl_r(), | ||
139 | pwr_falcon_cpuctl_startcpu_f(1)); | ||
140 | |||
141 | gk20a_writel(g, pwr_falcon_os_r(), desc->app_version); | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | |||
29 | void gv11b_init_pmu_ops(struct gpu_ops *gops) | 147 | void gv11b_init_pmu_ops(struct gpu_ops *gops) |
30 | { | 148 | { |
31 | gp10b_init_pmu_ops(gops); | 149 | gp10b_init_pmu_ops(gops); |
150 | gops->pmu.pmu_nsbootstrap = gv11b_pmu_bootstrap; | ||
32 | gops->pmu.is_pmu_supported = gv11b_is_pmu_supported; | 151 | gops->pmu.is_pmu_supported = gv11b_is_pmu_supported; |
33 | } | 152 | } |