gm200.c (f15cde64b66161bfa74fb58f4e5697d8265b802e) gm200.c (0e44c21708761977dcbea9b846b51a6fb684907a)
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

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

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 <subdev/mc.h>
25#include <subdev/timer.h>
26
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

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

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 <subdev/mc.h>
25#include <subdev/timer.h>
26
27static 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}
36
37static void
38gm200_flcn_pio_dmem_wr_init(struct nvkm_falcon *falcon, u8 port, bool sec, u32 dmem_base)
39{
40 nvkm_falcon_wr32(falcon, 0x1c0 + (port * 8), BIT(24) | dmem_base);
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,
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
57static void
58gm200_flcn_pio_imem_wr(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len, u16 tag)
59{
60 nvkm_falcon_wr32(falcon, 0x188 + (port * 0x10), tag++);
61 while (len >= 4) {
62 nvkm_falcon_wr32(falcon, 0x184 + (port * 0x10), *(u32 *)img);
63 img += 4;
64 len -= 4;
65 }
66}
67
68const struct nvkm_falcon_func_pio
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
27int
28gm200_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *falcon)
29{
30 nvkm_falcon_mask(falcon, 0x040, 0x00000000, 0x00000000);
31
32 if (nvkm_msec(falcon->owner->device, 10,
33 if (!(nvkm_falcon_rd32(falcon, 0x10c) & 0x00000006))
34 break;

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

76 if (falcon->func->reset_eng) {
77 ret = falcon->func->reset_eng(falcon);
78 if (ret)
79 return ret;
80 }
81
82 return 0;
83}
76int
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;

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

125 if (falcon->func->reset_eng) {
126 ret = falcon->func->reset_eng(falcon);
127 if (ret)
128 return ret;
129 }
130
131 return 0;
132}
133
134int
135gm200_flcn_fw_boot(struct nvkm_falcon_fw *fw, u32 *pmbox0, u32 *pmbox1, u32 mbox0_ok, u32 irqsclr)
136{
137 struct nvkm_falcon *falcon = fw->falcon;
138 u32 mbox0, mbox1;
139 int ret = 0;
140
141 nvkm_falcon_wr32(falcon, 0x040, pmbox0 ? *pmbox0 : 0xcafebeef);
142 if (pmbox1)
143 nvkm_falcon_wr32(falcon, 0x044, *pmbox1);
144
145 nvkm_falcon_wr32(falcon, 0x104, fw->boot_addr);
146 nvkm_falcon_wr32(falcon, 0x100, 0x00000002);
147
148 if (nvkm_msec(falcon->owner->device, 2000,
149 if (nvkm_falcon_rd32(falcon, 0x100) & 0x00000010)
150 break;
151 ) < 0)
152 ret = -ETIMEDOUT;
153
154 mbox0 = nvkm_falcon_rd32(falcon, 0x040);
155 mbox1 = nvkm_falcon_rd32(falcon, 0x044);
156 if (FLCN_ERRON(falcon, ret || mbox0 != mbox0_ok, "mbox %08x %08x", mbox0, mbox1))
157 ret = ret ?: -EIO;
158
159 if (irqsclr)
160 nvkm_falcon_mask(falcon, 0x004, 0xffffffff, irqsclr);
161
162 return ret;
163}
164
165int
166gm200_flcn_fw_load(struct nvkm_falcon_fw *fw)
167{
168 struct nvkm_falcon *falcon = fw->falcon;
169 int ret;
170
171 if (1) {
172 nvkm_falcon_mask(falcon, 0x624, 0x00000080, 0x00000080);
173 nvkm_falcon_wr32(falcon, 0x10c, 0x00000000);
174 }
175
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)
184 return ret;
185
186 ret = nvkm_falcon_pio_wr(falcon, fw->fw.img + fw->dmem_base_img, fw->dmem_base_img, 0,
187 DMEM, fw->dmem_base, fw->dmem_size, 0, false);
188 if (ret)
189 return ret;
190
191 return 0;
192}
193
194int
195gm200_flcn_fw_reset(struct nvkm_falcon_fw *fw)
196{
197 return nvkm_falcon_reset(fw->falcon);
198}
199
200int
201gm200_flcn_fw_signature(struct nvkm_falcon_fw *fw, u32 *sig_base_src)
202{
203 struct nvkm_falcon *falcon = fw->falcon;
204 u32 addr = falcon->func->debug;
205 int ret = 0;
206
207 if (addr) {
208 ret = nvkm_falcon_enable(falcon);
209 if (ret)
210 return ret;
211
212 if (nvkm_falcon_rd32(falcon, addr) & 0x00100000) {
213 *sig_base_src = fw->sig_base_dbg;
214 return 1;
215 }
216 }
217
218 return ret;
219}
220
221const struct nvkm_falcon_fw_func
222gm200_flcn_fw = {
223 .signature = gm200_flcn_fw_signature,
224 .reset = gm200_flcn_fw_reset,
225 .load = gm200_flcn_fw_load,
226 .boot = gm200_flcn_fw_boot,
227};