2 * Copyright 2012 Red Hat Inc.
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
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
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.
23 #include <engine/falcon.h>
24 #include <subdev/timer.h>
27 _nouveau_falcon_rd32(struct nouveau_object
*object
, u64 addr
)
29 struct nouveau_falcon
*falcon
= (void *)object
;
30 return nv_rd32(falcon
, falcon
->addr
+ addr
);
34 _nouveau_falcon_wr32(struct nouveau_object
*object
, u64 addr
, u32 data
)
36 struct nouveau_falcon
*falcon
= (void *)object
;
37 nv_wr32(falcon
, falcon
->addr
+ addr
, data
);
41 _nouveau_falcon_init(struct nouveau_object
*object
)
43 struct nouveau_device
*device
= nv_device(object
);
44 struct nouveau_falcon
*falcon
= (void *)object
;
45 const struct firmware
*fw
;
46 char name
[32] = "internal";
50 /* enable engine, and determine its capabilities */
51 ret
= nouveau_engine_init(&falcon
->base
);
55 if (device
->chipset
< 0xa3 ||
56 device
->chipset
== 0xaa || device
->chipset
== 0xac) {
58 falcon
->secret
= (falcon
->addr
== 0x087000) ? 1 : 0;
60 caps
= nv_ro32(falcon
, 0x12c);
61 falcon
->version
= (caps
& 0x0000000f);
62 falcon
->secret
= (caps
& 0x00000030) >> 4;
65 caps
= nv_ro32(falcon
, 0x108);
66 falcon
->code
.limit
= (caps
& 0x000001ff) << 8;
67 falcon
->data
.limit
= (caps
& 0x0003fe00) >> 1;
69 nv_debug(falcon
, "falcon version: %d\n", falcon
->version
);
70 nv_debug(falcon
, "secret level: %d\n", falcon
->secret
);
71 nv_debug(falcon
, "code limit: %d\n", falcon
->code
.limit
);
72 nv_debug(falcon
, "data limit: %d\n", falcon
->data
.limit
);
74 /* wait for 'uc halted' to be signalled before continuing */
75 if (falcon
->secret
&& falcon
->version
< 4) {
77 nv_wait(falcon
, 0x008, 0x00000010, 0x00000010);
79 nv_wait(falcon
, 0x180, 0x80000000, 0);
80 nv_wo32(falcon
, 0x004, 0x00000010);
83 /* disable all interrupts */
84 nv_wo32(falcon
, 0x014, 0xffffffff);
86 /* no default ucode provided by the engine implementation, try and
87 * locate a "self-bootstrapping" firmware image for the engine
89 if (!falcon
->code
.data
) {
90 snprintf(name
, sizeof(name
), "nouveau/nv%02x_fuc%03x",
91 device
->chipset
, falcon
->addr
>> 12);
93 ret
= request_firmware(&fw
, name
, &device
->pdev
->dev
);
95 falcon
->code
.data
= kmemdup(fw
->data
, fw
->size
, GFP_KERNEL
);
96 falcon
->code
.size
= fw
->size
;
97 falcon
->data
.data
= NULL
;
98 falcon
->data
.size
= 0;
102 falcon
->external
= true;
105 /* next step is to try and load "static code/data segment" firmware
106 * images for the engine
108 if (!falcon
->code
.data
) {
109 snprintf(name
, sizeof(name
), "nouveau/nv%02x_fuc%03xd",
110 device
->chipset
, falcon
->addr
>> 12);
112 ret
= request_firmware(&fw
, name
, &device
->pdev
->dev
);
114 nv_error(falcon
, "unable to load firmware data\n");
118 falcon
->data
.data
= kmemdup(fw
->data
, fw
->size
, GFP_KERNEL
);
119 falcon
->data
.size
= fw
->size
;
120 release_firmware(fw
);
121 if (!falcon
->data
.data
)
124 snprintf(name
, sizeof(name
), "nouveau/nv%02x_fuc%03xc",
125 device
->chipset
, falcon
->addr
>> 12);
127 ret
= request_firmware(&fw
, name
, &device
->pdev
->dev
);
129 nv_error(falcon
, "unable to load firmware code\n");
133 falcon
->code
.data
= kmemdup(fw
->data
, fw
->size
, GFP_KERNEL
);
134 falcon
->code
.size
= fw
->size
;
135 release_firmware(fw
);
136 if (!falcon
->code
.data
)
140 nv_debug(falcon
, "firmware: %s (%s)\n", name
, falcon
->data
.data
?
141 "static code/data segments" : "self-bootstrapping");
143 /* ensure any "self-bootstrapping" firmware image is in vram */
144 if (!falcon
->data
.data
&& !falcon
->core
) {
145 ret
= nouveau_gpuobj_new(object
->parent
, NULL
,
146 falcon
->code
.size
, 256, 0,
149 nv_error(falcon
, "core allocation failed, %d\n", ret
);
153 for (i
= 0; i
< falcon
->code
.size
; i
+= 4)
154 nv_wo32(falcon
->core
, i
, falcon
->code
.data
[i
/ 4]);
157 /* upload firmware bootloader (or the full code segments) */
159 if (device
->card_type
< NV_C0
)
160 nv_wo32(falcon
, 0x618, 0x04000000);
162 nv_wo32(falcon
, 0x618, 0x00000114);
163 nv_wo32(falcon
, 0x11c, 0);
164 nv_wo32(falcon
, 0x110, falcon
->core
->addr
>> 8);
165 nv_wo32(falcon
, 0x114, 0);
166 nv_wo32(falcon
, 0x118, 0x00006610);
168 if (falcon
->code
.size
> falcon
->code
.limit
||
169 falcon
->data
.size
> falcon
->data
.limit
) {
170 nv_error(falcon
, "ucode exceeds falcon limit(s)\n");
174 if (falcon
->version
< 3) {
175 nv_wo32(falcon
, 0xff8, 0x00100000);
176 for (i
= 0; i
< falcon
->code
.size
/ 4; i
++)
177 nv_wo32(falcon
, 0xff4, falcon
->code
.data
[i
]);
179 nv_wo32(falcon
, 0x180, 0x01000000);
180 for (i
= 0; i
< falcon
->code
.size
/ 4; i
++) {
182 nv_wo32(falcon
, 0x188, i
>> 6);
183 nv_wo32(falcon
, 0x184, falcon
->code
.data
[i
]);
188 /* upload data segment (if necessary), zeroing the remainder */
189 if (falcon
->version
< 3) {
190 nv_wo32(falcon
, 0xff8, 0x00000000);
191 for (i
= 0; !falcon
->core
&& i
< falcon
->data
.size
/ 4; i
++)
192 nv_wo32(falcon
, 0xff4, falcon
->data
.data
[i
]);
193 for (; i
< falcon
->data
.limit
; i
+= 4)
194 nv_wo32(falcon
, 0xff4, 0x00000000);
196 nv_wo32(falcon
, 0x1c0, 0x01000000);
197 for (i
= 0; !falcon
->core
&& i
< falcon
->data
.size
/ 4; i
++)
198 nv_wo32(falcon
, 0x1c4, falcon
->data
.data
[i
]);
199 for (; i
< falcon
->data
.limit
/ 4; i
++)
200 nv_wo32(falcon
, 0x1c4, 0x00000000);
203 /* start it running */
204 nv_wo32(falcon
, 0x10c, 0x00000001); /* BLOCK_ON_FIFO */
205 nv_wo32(falcon
, 0x104, 0x00000000); /* ENTRY */
206 nv_wo32(falcon
, 0x100, 0x00000002); /* TRIGGER */
207 nv_wo32(falcon
, 0x048, 0x00000003); /* FIFO | CHSW */
212 _nouveau_falcon_fini(struct nouveau_object
*object
, bool suspend
)
214 struct nouveau_falcon
*falcon
= (void *)object
;
217 nouveau_gpuobj_ref(NULL
, &falcon
->core
);
218 if (falcon
->external
) {
219 kfree(falcon
->data
.data
);
220 kfree(falcon
->code
.data
);
221 falcon
->code
.data
= NULL
;
225 nv_mo32(falcon
, 0x048, 0x00000003, 0x00000000);
226 nv_wo32(falcon
, 0x014, 0xffffffff);
228 return nouveau_engine_fini(&falcon
->base
, suspend
);
232 nouveau_falcon_create_(struct nouveau_object
*parent
,
233 struct nouveau_object
*engine
,
234 struct nouveau_oclass
*oclass
, u32 addr
, bool enable
,
235 const char *iname
, const char *fname
,
236 int length
, void **pobject
)
238 struct nouveau_falcon
*falcon
;
241 ret
= nouveau_engine_create_(parent
, engine
, oclass
, enable
, iname
,
242 fname
, length
, pobject
);
This page took 0.039276 seconds and 5 git commands to generate.