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
;
74 if (pci_find_capability(device
->pdev
, PCI_CAP_ID_AGP
))
75 args
->v0
.platform
= NV_DEVICE_INFO_V0_AGP
;
77 if (pci_is_pcie(device
->pdev
))
78 args
->v0
.platform
= NV_DEVICE_INFO_V0_PCIE
;
80 args
->v0
.platform
= NV_DEVICE_INFO_V0_PCI
;
82 args
->v0
.platform
= NV_DEVICE_INFO_V0_SOC
;
87 switch (device
->card_type
) {
88 case NV_04
: args
->v0
.family
= NV_DEVICE_INFO_V0_TNT
; break;
90 case NV_11
: args
->v0
.family
= NV_DEVICE_INFO_V0_CELSIUS
; break;
91 case NV_20
: args
->v0
.family
= NV_DEVICE_INFO_V0_KELVIN
; break;
92 case NV_30
: args
->v0
.family
= NV_DEVICE_INFO_V0_RANKINE
; break;
93 case NV_40
: args
->v0
.family
= NV_DEVICE_INFO_V0_CURIE
; break;
94 case NV_50
: args
->v0
.family
= NV_DEVICE_INFO_V0_TESLA
; break;
95 case NV_C0
: args
->v0
.family
= NV_DEVICE_INFO_V0_FERMI
; break;
96 case NV_E0
: args
->v0
.family
= NV_DEVICE_INFO_V0_KEPLER
; break;
97 case GM100
: args
->v0
.family
= NV_DEVICE_INFO_V0_MAXWELL
; break;
103 args
->v0
.chipset
= device
->chipset
;
104 args
->v0
.revision
= device
->chiprev
;
106 args
->v0
.ram_size
= args
->v0
.ram_user
= fb
->ram
->size
;
108 args
->v0
.ram_size
= args
->v0
.ram_user
= 0;
109 if (imem
&& args
->v0
.ram_size
> 0)
110 args
->v0
.ram_user
= args
->v0
.ram_user
- imem
->reserved
;
112 strncpy(args
->v0
.chip
, device
->chip
->name
, sizeof(args
->v0
.chip
));
113 strncpy(args
->v0
.name
, device
->name
, sizeof(args
->v0
.name
));
118 nvkm_udevice_time(struct nvkm_udevice
*udev
, void *data
, u32 size
)
120 struct nvkm_device
*device
= udev
->device
;
122 struct nv_device_time_v0 v0
;
126 if (nvif_unpack(args
->v0
, 0, 0, false)) {
127 args
->v0
.time
= nvkm_timer_read(device
->timer
);
134 nvkm_udevice_mthd(struct nvkm_object
*object
, u32 mthd
, void *data
, u32 size
)
136 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
138 case NV_DEVICE_V0_INFO
:
139 return nvkm_udevice_info(udev
, data
, size
);
140 case NV_DEVICE_V0_TIME
:
141 return nvkm_udevice_time(udev
, data
, size
);
149 nvkm_udevice_rd08(struct nvkm_object
*object
, u64 addr
, u8
*data
)
151 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
152 *data
= nvkm_rd08(udev
->device
, addr
);
157 nvkm_udevice_rd16(struct nvkm_object
*object
, u64 addr
, u16
*data
)
159 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
160 *data
= nvkm_rd16(udev
->device
, addr
);
165 nvkm_udevice_rd32(struct nvkm_object
*object
, u64 addr
, u32
*data
)
167 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
168 *data
= nvkm_rd32(udev
->device
, addr
);
173 nvkm_udevice_wr08(struct nvkm_object
*object
, u64 addr
, u8 data
)
175 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
176 nvkm_wr08(udev
->device
, addr
, data
);
181 nvkm_udevice_wr16(struct nvkm_object
*object
, u64 addr
, u16 data
)
183 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
184 nvkm_wr16(udev
->device
, addr
, data
);
189 nvkm_udevice_wr32(struct nvkm_object
*object
, u64 addr
, u32 data
)
191 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
192 nvkm_wr32(udev
->device
, addr
, data
);
197 nvkm_udevice_map(struct nvkm_object
*object
, u64
*addr
, u32
*size
)
199 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
200 struct nvkm_device
*device
= udev
->device
;
201 *addr
= nv_device_resource_start(device
, 0);
202 *size
= nv_device_resource_len(device
, 0);
207 nvkm_udevice_fini(struct nvkm_object
*object
, bool suspend
)
209 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
210 struct nvkm_device
*device
= udev
->device
;
213 mutex_lock(&device
->mutex
);
214 if (!--device
->refcount
) {
215 ret
= nvkm_device_fini(device
, suspend
);
216 if (ret
&& suspend
) {
223 mutex_unlock(&device
->mutex
);
228 nvkm_udevice_init(struct nvkm_object
*object
)
230 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
231 struct nvkm_device
*device
= udev
->device
;
234 mutex_lock(&device
->mutex
);
235 if (!device
->refcount
++) {
236 ret
= nvkm_device_init(device
);
244 mutex_unlock(&device
->mutex
);
249 nvkm_udevice_child_new(const struct nvkm_oclass
*oclass
,
250 void *data
, u32 size
, struct nvkm_object
**pobject
)
252 struct nvkm_udevice
*udev
= nvkm_udevice(oclass
->parent
);
253 const struct nvkm_device_oclass
*sclass
= oclass
->priv
;
254 return sclass
->ctor(udev
->device
, oclass
, data
, size
, pobject
);
258 nvkm_udevice_child_get(struct nvkm_object
*object
, int index
,
259 struct nvkm_oclass
*oclass
)
261 struct nvkm_udevice
*udev
= nvkm_udevice(object
);
262 struct nvkm_device
*device
= udev
->device
;
263 struct nvkm_engine
*engine
;
264 u64 mask
= (1ULL << NVDEV_ENGINE_DMAOBJ
) |
265 (1ULL << NVDEV_ENGINE_FIFO
) |
266 (1ULL << NVDEV_ENGINE_DISP
) |
267 (1ULL << NVDEV_ENGINE_PM
);
268 const struct nvkm_device_oclass
*sclass
= NULL
;
271 for (; i
= __ffs64(mask
), mask
&& !sclass
; mask
&= ~(1ULL << i
)) {
272 if (!(engine
= nvkm_device_engine(device
, i
)) ||
273 !(engine
->func
->base
.sclass
))
275 oclass
->engine
= engine
;
277 index
-= engine
->func
->base
.sclass(oclass
, index
, &sclass
);
282 case 0: sclass
= &nvkm_control_oclass
; break;
286 oclass
->base
= sclass
->base
;
289 oclass
->ctor
= nvkm_udevice_child_new
;
290 oclass
->priv
= sclass
;
294 static const struct nvkm_object_func
295 nvkm_udevice_super
= {
296 .init
= nvkm_udevice_init
,
297 .fini
= nvkm_udevice_fini
,
298 .mthd
= nvkm_udevice_mthd
,
299 .map
= nvkm_udevice_map
,
300 .rd08
= nvkm_udevice_rd08
,
301 .rd16
= nvkm_udevice_rd16
,
302 .rd32
= nvkm_udevice_rd32
,
303 .wr08
= nvkm_udevice_wr08
,
304 .wr16
= nvkm_udevice_wr16
,
305 .wr32
= nvkm_udevice_wr32
,
306 .sclass
= nvkm_udevice_child_get
,
309 static const struct nvkm_object_func
311 .init
= nvkm_udevice_init
,
312 .fini
= nvkm_udevice_fini
,
313 .mthd
= nvkm_udevice_mthd
,
314 .sclass
= nvkm_udevice_child_get
,
318 nvkm_udevice_new(const struct nvkm_oclass
*oclass
, void *data
, u32 size
,
319 struct nvkm_object
**pobject
)
322 struct nv_device_v0 v0
;
324 struct nvkm_client
*client
= oclass
->client
;
325 struct nvkm_object
*parent
= &client
->object
;
326 const struct nvkm_object_func
*func
;
327 struct nvkm_udevice
*udev
;
330 nvif_ioctl(parent
, "create device size %d\n", size
);
331 if (nvif_unpack(args
->v0
, 0, 0, false)) {
332 nvif_ioctl(parent
, "create device v%d device %016llx\n",
333 args
->v0
.version
, args
->v0
.device
);
337 /* give priviledged clients register access */
339 func
= &nvkm_udevice_super
;
341 func
= &nvkm_udevice
;
343 if (!(udev
= kzalloc(sizeof(*udev
), GFP_KERNEL
)))
345 nvkm_object_ctor(func
, oclass
, &udev
->object
);
346 *pobject
= &udev
->object
;
348 /* find the device that matches what the client requested */
349 if (args
->v0
.device
!= ~0)
350 udev
->device
= nvkm_device_find(args
->v0
.device
);
352 udev
->device
= nvkm_device_find(client
->device
);
359 const struct nvkm_sclass
360 nvkm_udevice_sclass
= {
364 .ctor
= nvkm_udevice_new
,