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.
24 #define nvkm_udevice(p) container_of((p), struct nvkm_udevice, object)
28 #include <core/client.h>
29 #include <subdev/fb.h>
30 #include <subdev/instmem.h>
31 #include <subdev/timer.h>
33 #include <nvif/class.h>
34 #include <nvif/unpack.h>
37 struct nvkm_object object
;
38 struct nvkm_device
*device
;
42 nvkm_udevice_info(struct nvkm_udevice
*udev
, void *data
, u32 size
)
44 struct nvkm_object
*object
= &udev
->object
;
45 struct nvkm_device
*device
= udev
->device
;
46 struct nvkm_fb
*fb
= device
->fb
;
47 struct nvkm_instmem
*imem
= device
->imem
;
49 struct nv_device_info_v0 v0
;
53 nvif_ioctl(object
, "device info size %d\n", size
);
54 if (nvif_unpack(args
->v0
, 0, 0, false)) {
55 nvif_ioctl(object
, "device info vers %d\n", args
->v0
.version
);
59 switch (device
->chipset
) {
70 args
->v0
.platform
= NV_DEVICE_INFO_V0_IGP
;
73 switch (device
->type
) {
75 args
->v0
.platform
= NV_DEVICE_INFO_V0_PCI
;
78 args
->v0
.platform
= NV_DEVICE_INFO_V0_AGP
;
80 case NVKM_DEVICE_PCIE
:
81 args
->v0
.platform
= NV_DEVICE_INFO_V0_PCIE
;
83 case NVKM_DEVICE_TEGRA
:
84 args
->v0
.platform
= NV_DEVICE_INFO_V0_SOC
;
93 switch (device
->card_type
) {
94 case NV_04
: args
->v0
.family
= NV_DEVICE_INFO_V0_TNT
; break;
96 case NV_11
: args
->v0
.family
= NV_DEVICE_INFO_V0_CELSIUS
; break;
97 case NV_20
: args
->v0
.family
= NV_DEVICE_INFO_V0_KELVIN
; break;
98 case NV_30
: args
->v0
.family
= NV_DEVICE_INFO_V0_RANKINE
; break;
99 case NV_40
: args
->v0
.family
= NV_DEVICE_INFO_V0_CURIE
; break;
100 case NV_50
: args
->v0
.family
= NV_DEVICE_INFO_V0_TESLA
; break;
101 case NV_C0
: args
->v0
.family
= NV_DEVICE_INFO_V0_FERMI
; break;
102 case NV_E0
: args
->v0
.family
= NV_DEVICE_INFO_V0_KEPLER
; break;
103 case GM100
: args
->v0
.family
= NV_DEVICE_INFO_V0_MAXWELL
; break;
109 args
->v0
.chipset
= device
->chipset
;
110 args
->v0
.revision
= device
->chiprev
;
112 args
->v0
.ram_size
= args
->v0
.ram_user
= fb
->ram
->size
;
114 args
->v0
.ram_size
= args
->v0
.ram_user
= 0;
115 if (imem
&& args
->v0
.ram_size
> 0)
116 args
->v0
.ram_user
= args
->v0
.ram_user
- imem
->reserved
;
118 strncpy(args
->v0
.chip
, device
->chip
->name
, sizeof(args
->v0
.chip
));
119 strncpy(args
->v0
.name
, device
->name
, sizeof(args
->v0
.name
));
124 nvkm_udevice_time(struct nvkm_udevice
*udev
, void *data
, u32 size
)
126 struct nvkm_device
*device
= udev
->device
;
128 struct nv_device_time_v0 v0
;
132 if (nvif_unpack(args
->v0
, 0, 0, false)) {
133 args
->v0
.time
= nvkm_timer_read(device
->timer
);
140 nvkm_udevice_mthd(struct nvkm_object
*object
, u32 mthd
, void *data
, u32 size
)
142 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
144 case NV_DEVICE_V0_INFO
:
145 return nvkm_udevice_info(udev
, data
, size
);
146 case NV_DEVICE_V0_TIME
:
147 return nvkm_udevice_time(udev
, data
, size
);
155 nvkm_udevice_rd08(struct nvkm_object
*object
, u64 addr
, u8
*data
)
157 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
158 *data
= nvkm_rd08(udev
->device
, addr
);
163 nvkm_udevice_rd16(struct nvkm_object
*object
, u64 addr
, u16
*data
)
165 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
166 *data
= nvkm_rd16(udev
->device
, addr
);
171 nvkm_udevice_rd32(struct nvkm_object
*object
, u64 addr
, u32
*data
)
173 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
174 *data
= nvkm_rd32(udev
->device
, addr
);
179 nvkm_udevice_wr08(struct nvkm_object
*object
, u64 addr
, u8 data
)
181 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
182 nvkm_wr08(udev
->device
, addr
, data
);
187 nvkm_udevice_wr16(struct nvkm_object
*object
, u64 addr
, u16 data
)
189 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
190 nvkm_wr16(udev
->device
, addr
, data
);
195 nvkm_udevice_wr32(struct nvkm_object
*object
, u64 addr
, u32 data
)
197 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
198 nvkm_wr32(udev
->device
, addr
, data
);
203 nvkm_udevice_map(struct nvkm_object
*object
, u64
*addr
, u32
*size
)
205 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
206 struct nvkm_device
*device
= udev
->device
;
207 *addr
= device
->func
->resource_addr(device
, 0);
208 *size
= device
->func
->resource_size(device
, 0);
213 nvkm_udevice_fini(struct nvkm_object
*object
, bool suspend
)
215 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
216 struct nvkm_device
*device
= udev
->device
;
219 mutex_lock(&device
->mutex
);
220 if (!--device
->refcount
) {
221 ret
= nvkm_device_fini(device
, suspend
);
222 if (ret
&& suspend
) {
229 mutex_unlock(&device
->mutex
);
234 nvkm_udevice_init(struct nvkm_object
*object
)
236 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
237 struct nvkm_device
*device
= udev
->device
;
240 mutex_lock(&device
->mutex
);
241 if (!device
->refcount
++) {
242 ret
= nvkm_device_init(device
);
250 mutex_unlock(&device
->mutex
);
255 nvkm_udevice_child_new(const struct nvkm_oclass
*oclass
,
256 void *data
, u32 size
, struct nvkm_object
**pobject
)
258 struct nvkm_udevice
*udev
= nvkm_udevice(oclass
->parent
);
259 const struct nvkm_device_oclass
*sclass
= oclass
->priv
;
260 return sclass
->ctor(udev
->device
, oclass
, data
, size
, pobject
);
264 nvkm_udevice_child_get(struct nvkm_object
*object
, int index
,
265 struct nvkm_oclass
*oclass
)
267 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
268 struct nvkm_device
*device
= udev
->device
;
269 struct nvkm_engine
*engine
;
270 u64 mask
= (1ULL << NVKM_ENGINE_DMAOBJ
) |
271 (1ULL << NVKM_ENGINE_FIFO
) |
272 (1ULL << NVKM_ENGINE_DISP
) |
273 (1ULL << NVKM_ENGINE_PM
);
274 const struct nvkm_device_oclass
*sclass
= NULL
;
277 for (; i
= __ffs64(mask
), mask
&& !sclass
; mask
&= ~(1ULL << i
)) {
278 if (!(engine
= nvkm_device_engine(device
, i
)) ||
279 !(engine
->func
->base
.sclass
))
281 oclass
->engine
= engine
;
283 index
-= engine
->func
->base
.sclass(oclass
, index
, &sclass
);
288 case 0: sclass
= &nvkm_control_oclass
; break;
292 oclass
->base
= sclass
->base
;
295 oclass
->ctor
= nvkm_udevice_child_new
;
296 oclass
->priv
= sclass
;
300 static const struct nvkm_object_func
301 nvkm_udevice_super
= {
302 .init
= nvkm_udevice_init
,
303 .fini
= nvkm_udevice_fini
,
304 .mthd
= nvkm_udevice_mthd
,
305 .map
= nvkm_udevice_map
,
306 .rd08
= nvkm_udevice_rd08
,
307 .rd16
= nvkm_udevice_rd16
,
308 .rd32
= nvkm_udevice_rd32
,
309 .wr08
= nvkm_udevice_wr08
,
310 .wr16
= nvkm_udevice_wr16
,
311 .wr32
= nvkm_udevice_wr32
,
312 .sclass
= nvkm_udevice_child_get
,
315 static const struct nvkm_object_func
317 .init
= nvkm_udevice_init
,
318 .fini
= nvkm_udevice_fini
,
319 .mthd
= nvkm_udevice_mthd
,
320 .sclass
= nvkm_udevice_child_get
,
324 nvkm_udevice_new(const struct nvkm_oclass
*oclass
, void *data
, u32 size
,
325 struct nvkm_object
**pobject
)
328 struct nv_device_v0 v0
;
330 struct nvkm_client
*client
= oclass
->client
;
331 struct nvkm_object
*parent
= &client
->object
;
332 const struct nvkm_object_func
*func
;
333 struct nvkm_udevice
*udev
;
336 nvif_ioctl(parent
, "create device size %d\n", size
);
337 if (nvif_unpack(args
->v0
, 0, 0, false)) {
338 nvif_ioctl(parent
, "create device v%d device %016llx\n",
339 args
->v0
.version
, args
->v0
.device
);
343 /* give priviledged clients register access */
345 func
= &nvkm_udevice_super
;
347 func
= &nvkm_udevice
;
349 if (!(udev
= kzalloc(sizeof(*udev
), GFP_KERNEL
)))
351 nvkm_object_ctor(func
, oclass
, &udev
->object
);
352 *pobject
= &udev
->object
;
354 /* find the device that matches what the client requested */
355 if (args
->v0
.device
!= ~0)
356 udev
->device
= nvkm_device_find(args
->v0
.device
);
358 udev
->device
= nvkm_device_find(client
->device
);
365 const struct nvkm_sclass
366 nvkm_udevice_sclass
= {
370 .ctor
= nvkm_udevice_new
,