gm200.c (0e44c21708761977dcbea9b846b51a6fb684907a) gm200.c (2541626cfb794e57ba0575a6920826f591f7ced0)
1/*
2 * Copyright 2022 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the

--- 7 unchanged lines hidden (view full) ---

16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "priv.h"
23
1/*
2 * Copyright 2022 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the

--- 7 unchanged lines hidden (view full) ---

16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "priv.h"
23
24#include <core/memory.h>
24#include <subdev/mc.h>
25#include <subdev/timer.h>
26
27static void
25#include <subdev/mc.h>
26#include <subdev/timer.h>
27
28static void
29gm200_flcn_pio_dmem_rd(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len)
30{
31 while (len >= 4) {
32 *(u32 *)img = nvkm_falcon_rd32(falcon, 0x1c4 + (port * 8));
33 img += 4;
34 len -= 4;
35 }
36}
37
38static void
39gm200_flcn_pio_dmem_rd_init(struct nvkm_falcon *falcon, u8 port, u32 dmem_base)
40{
41 nvkm_falcon_wr32(falcon, 0x1c0 + (port * 8), BIT(25) | dmem_base);
42}
43
44static void
28gm200_flcn_pio_dmem_wr(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len, u16 tag)
29{
30 while (len >= 4) {
31 nvkm_falcon_wr32(falcon, 0x1c4 + (port * 8), *(u32 *)img);
32 img += 4;
33 len -= 4;
34 }
35}

--- 5 unchanged lines hidden (view full) ---

41}
42
43const struct nvkm_falcon_func_pio
44gm200_flcn_dmem_pio = {
45 .min = 4,
46 .max = 0x100,
47 .wr_init = gm200_flcn_pio_dmem_wr_init,
48 .wr = gm200_flcn_pio_dmem_wr,
45gm200_flcn_pio_dmem_wr(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len, u16 tag)
46{
47 while (len >= 4) {
48 nvkm_falcon_wr32(falcon, 0x1c4 + (port * 8), *(u32 *)img);
49 img += 4;
50 len -= 4;
51 }
52}

--- 5 unchanged lines hidden (view full) ---

58}
59
60const struct nvkm_falcon_func_pio
61gm200_flcn_dmem_pio = {
62 .min = 4,
63 .max = 0x100,
64 .wr_init = gm200_flcn_pio_dmem_wr_init,
65 .wr = gm200_flcn_pio_dmem_wr,
66 .rd_init = gm200_flcn_pio_dmem_rd_init,
67 .rd = gm200_flcn_pio_dmem_rd,
49};
50
51static void
52gm200_flcn_pio_imem_wr_init(struct nvkm_falcon *falcon, u8 port, bool sec, u32 imem_base)
53{
54 nvkm_falcon_wr32(falcon, 0x180 + (port * 0x10), (sec ? BIT(28) : 0) | BIT(24) | imem_base);
55}
56

--- 12 unchanged lines hidden (view full) ---

69gm200_flcn_imem_pio = {
70 .min = 0x100,
71 .max = 0x100,
72 .wr_init = gm200_flcn_pio_imem_wr_init,
73 .wr = gm200_flcn_pio_imem_wr,
74};
75
76int
68};
69
70static void
71gm200_flcn_pio_imem_wr_init(struct nvkm_falcon *falcon, u8 port, bool sec, u32 imem_base)
72{
73 nvkm_falcon_wr32(falcon, 0x180 + (port * 0x10), (sec ? BIT(28) : 0) | BIT(24) | imem_base);
74}
75

--- 12 unchanged lines hidden (view full) ---

88gm200_flcn_imem_pio = {
89 .min = 0x100,
90 .max = 0x100,
91 .wr_init = gm200_flcn_pio_imem_wr_init,
92 .wr = gm200_flcn_pio_imem_wr,
93};
94
95int
96gm200_flcn_bind_stat(struct nvkm_falcon *falcon, bool intr)
97{
98 if (intr && !(nvkm_falcon_rd32(falcon, 0x008) & 0x00000008))
99 return -1;
100
101 return (nvkm_falcon_rd32(falcon, 0x0dc) & 0x00007000) >> 12;
102}
103
104void
105gm200_flcn_bind_inst(struct nvkm_falcon *falcon, int target, u64 addr)
106{
107 nvkm_falcon_mask(falcon, 0x604, 0x00000007, 0x00000000); /* DMAIDX_VIRT */
108 nvkm_falcon_wr32(falcon, 0x054, (1 << 30) | (target << 28) | (addr >> 12));
109 nvkm_falcon_mask(falcon, 0x090, 0x00010000, 0x00010000);
110 nvkm_falcon_mask(falcon, 0x0a4, 0x00000008, 0x00000008);
111}
112
113int
77gm200_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *falcon)
78{
79 nvkm_falcon_mask(falcon, 0x040, 0x00000000, 0x00000000);
80
81 if (nvkm_msec(falcon->owner->device, 10,
82 if (!(nvkm_falcon_rd32(falcon, 0x10c) & 0x00000006))
83 break;
84 ) < 0)

--- 76 unchanged lines hidden (view full) ---

161
162 return ret;
163}
164
165int
166gm200_flcn_fw_load(struct nvkm_falcon_fw *fw)
167{
168 struct nvkm_falcon *falcon = fw->falcon;
114gm200_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *falcon)
115{
116 nvkm_falcon_mask(falcon, 0x040, 0x00000000, 0x00000000);
117
118 if (nvkm_msec(falcon->owner->device, 10,
119 if (!(nvkm_falcon_rd32(falcon, 0x10c) & 0x00000006))
120 break;
121 ) < 0)

--- 76 unchanged lines hidden (view full) ---

198
199 return ret;
200}
201
202int
203gm200_flcn_fw_load(struct nvkm_falcon_fw *fw)
204{
205 struct nvkm_falcon *falcon = fw->falcon;
169 int ret;
206 int target, ret;
170
207
171 if (1) {
208 if (fw->inst) {
209 nvkm_falcon_mask(falcon, 0x048, 0x00000001, 0x00000001);
210
211 switch (nvkm_memory_target(fw->inst)) {
212 case NVKM_MEM_TARGET_VRAM: target = 0; break;
213 case NVKM_MEM_TARGET_HOST: target = 2; break;
214 case NVKM_MEM_TARGET_NCOH: target = 3; break;
215 default:
216 WARN_ON(1);
217 return -EINVAL;
218 }
219
220 falcon->func->bind_inst(falcon, target, nvkm_memory_addr(fw->inst));
221
222 if (nvkm_msec(falcon->owner->device, 10,
223 if (falcon->func->bind_stat(falcon, falcon->func->bind_intr) == 5)
224 break;
225 ) < 0)
226 return -ETIMEDOUT;
227
228 nvkm_falcon_mask(falcon, 0x004, 0x00000008, 0x00000008);
229 nvkm_falcon_mask(falcon, 0x058, 0x00000002, 0x00000002);
230
231 if (nvkm_msec(falcon->owner->device, 10,
232 if (falcon->func->bind_stat(falcon, false) == 0)
233 break;
234 ) < 0)
235 return -ETIMEDOUT;
236 } else {
172 nvkm_falcon_mask(falcon, 0x624, 0x00000080, 0x00000080);
173 nvkm_falcon_wr32(falcon, 0x10c, 0x00000000);
174 }
175
237 nvkm_falcon_mask(falcon, 0x624, 0x00000080, 0x00000080);
238 nvkm_falcon_wr32(falcon, 0x10c, 0x00000000);
239 }
240
241 if (fw->boot) {
242 switch (nvkm_memory_target(&fw->fw.mem.memory)) {
243 case NVKM_MEM_TARGET_VRAM: target = 4; break;
244 case NVKM_MEM_TARGET_HOST: target = 5; break;
245 case NVKM_MEM_TARGET_NCOH: target = 6; break;
246 default:
247 WARN_ON(1);
248 return -EINVAL;
249 }
250
251 ret = nvkm_falcon_pio_wr(falcon, fw->boot, 0, 0,
252 IMEM, falcon->code.limit - fw->boot_size, fw->boot_size,
253 fw->boot_addr >> 8, false);
254 if (ret)
255 return ret;
256
257 return fw->func->load_bld(fw);
258 }
259
176 ret = nvkm_falcon_pio_wr(falcon, fw->fw.img + fw->nmem_base_img, fw->nmem_base_img, 0,
177 IMEM, fw->nmem_base, fw->nmem_size, fw->nmem_base >> 8, false);
178 if (ret)
179 return ret;
180
181 ret = nvkm_falcon_pio_wr(falcon, fw->fw.img + fw->imem_base_img, fw->imem_base_img, 0,
182 IMEM, fw->imem_base, fw->imem_size, fw->imem_base >> 8, true);
183 if (ret)

--- 44 unchanged lines hidden ---
260 ret = nvkm_falcon_pio_wr(falcon, fw->fw.img + fw->nmem_base_img, fw->nmem_base_img, 0,
261 IMEM, fw->nmem_base, fw->nmem_size, fw->nmem_base >> 8, false);
262 if (ret)
263 return ret;
264
265 ret = nvkm_falcon_pio_wr(falcon, fw->fw.img + fw->imem_base_img, fw->imem_base_img, 0,
266 IMEM, fw->imem_base, fw->imem_size, fw->imem_base >> 8, true);
267 if (ret)

--- 44 unchanged lines hidden ---