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.
25 #include <core/object.h>
26 #include <core/device.h>
27 #include <core/client.h>
28 #include <core/device.h>
29 #include <core/option.h>
31 #include <core/class.h>
33 #include <subdev/device.h>
35 static DEFINE_MUTEX(nv_devices_mutex
);
36 static LIST_HEAD(nv_devices
);
38 struct nouveau_device
*
39 nouveau_device_find(u64 name
)
41 struct nouveau_device
*device
, *match
= NULL
;
42 mutex_lock(&nv_devices_mutex
);
43 list_for_each_entry(device
, &nv_devices
, head
) {
44 if (device
->handle
== name
) {
49 mutex_unlock(&nv_devices_mutex
);
53 /******************************************************************************
54 * nouveau_devobj (0x0080): class implementation
55 *****************************************************************************/
56 struct nouveau_devobj
{
57 struct nouveau_parent base
;
58 struct nouveau_object
*subdev
[NVDEV_SUBDEV_NR
];
62 static const u64 disable_map
[] = {
63 [NVDEV_SUBDEV_VBIOS
] = NV_DEVICE_DISABLE_VBIOS
,
64 [NVDEV_SUBDEV_GPIO
] = NV_DEVICE_DISABLE_CORE
,
65 [NVDEV_SUBDEV_I2C
] = NV_DEVICE_DISABLE_CORE
,
66 [NVDEV_SUBDEV_DEVINIT
] = NV_DEVICE_DISABLE_CORE
,
67 [NVDEV_SUBDEV_MC
] = NV_DEVICE_DISABLE_CORE
,
68 [NVDEV_SUBDEV_TIMER
] = NV_DEVICE_DISABLE_CORE
,
69 [NVDEV_SUBDEV_FB
] = NV_DEVICE_DISABLE_CORE
,
70 [NVDEV_SUBDEV_VM
] = NV_DEVICE_DISABLE_CORE
,
71 [NVDEV_SUBDEV_INSTMEM
] = NV_DEVICE_DISABLE_CORE
,
72 [NVDEV_SUBDEV_BAR
] = NV_DEVICE_DISABLE_CORE
,
73 [NVDEV_SUBDEV_VOLT
] = NV_DEVICE_DISABLE_CORE
,
74 [NVDEV_SUBDEV_FAN0
] = NV_DEVICE_DISABLE_CORE
,
75 [NVDEV_SUBDEV_CLOCK
] = NV_DEVICE_DISABLE_CORE
,
76 [NVDEV_SUBDEV_THERM
] = NV_DEVICE_DISABLE_CORE
,
77 [NVDEV_ENGINE_DMAOBJ
] = NV_DEVICE_DISABLE_CORE
,
78 [NVDEV_ENGINE_GR
] = NV_DEVICE_DISABLE_GRAPH
,
79 [NVDEV_ENGINE_MPEG
] = NV_DEVICE_DISABLE_MPEG
,
80 [NVDEV_ENGINE_ME
] = NV_DEVICE_DISABLE_ME
,
81 [NVDEV_ENGINE_VP
] = NV_DEVICE_DISABLE_VP
,
82 [NVDEV_ENGINE_CRYPT
] = NV_DEVICE_DISABLE_CRYPT
,
83 [NVDEV_ENGINE_BSP
] = NV_DEVICE_DISABLE_BSP
,
84 [NVDEV_ENGINE_PPP
] = NV_DEVICE_DISABLE_PPP
,
85 [NVDEV_ENGINE_COPY0
] = NV_DEVICE_DISABLE_COPY0
,
86 [NVDEV_ENGINE_COPY1
] = NV_DEVICE_DISABLE_COPY1
,
87 [NVDEV_ENGINE_UNK1C1
] = NV_DEVICE_DISABLE_UNK1C1
,
88 [NVDEV_ENGINE_FIFO
] = NV_DEVICE_DISABLE_FIFO
,
89 [NVDEV_ENGINE_DISP
] = NV_DEVICE_DISABLE_DISP
,
90 [NVDEV_SUBDEV_NR
] = 0,
94 nouveau_devobj_ctor(struct nouveau_object
*parent
,
95 struct nouveau_object
*engine
,
96 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
97 struct nouveau_object
**pobject
)
99 struct nouveau_client
*client
= nv_client(parent
);
100 struct nouveau_object
*subdev
= NULL
;
101 struct nouveau_device
*device
;
102 struct nouveau_devobj
*devobj
;
103 struct nv_device_class
*args
= data
;
104 u64 disable
, boot0
, strap
;
105 u64 mmio_base
, mmio_size
;
109 if (size
< sizeof(struct nv_device_class
))
112 /* find the device subdev that matches what the client requested */
113 device
= nv_device(client
->device
);
114 if (args
->device
!= ~0) {
115 device
= nouveau_device_find(args
->device
);
120 ret
= nouveau_parent_create(parent
, nv_object(device
), oclass
, 0, NULL
,
121 (1ULL << NVDEV_ENGINE_DMAOBJ
) |
122 (1ULL << NVDEV_ENGINE_FIFO
) |
123 (1ULL << NVDEV_ENGINE_DISP
), &devobj
);
124 *pobject
= nv_object(devobj
);
128 mmio_base
= pci_resource_start(device
->pdev
, 0);
129 mmio_size
= pci_resource_len(device
->pdev
, 0);
131 /* translate api disable mask into internal mapping */
132 disable
= args
->debug0
;
133 for (i
= 0; i
< NVDEV_SUBDEV_NR
; i
++) {
134 if (args
->disable
& disable_map
[i
])
135 disable
|= (1ULL << i
);
138 /* identify the chipset, and determine classes of subdev/engines */
139 if (!(args
->disable
& NV_DEVICE_DISABLE_IDENTIFY
) &&
140 !device
->card_type
) {
141 map
= ioremap(mmio_base
, 0x102000);
145 /* switch mmio to cpu's native endianness */
147 if (ioread32_native(map
+ 0x000004) != 0x00000000)
149 if (ioread32_native(map
+ 0x000004) == 0x00000000)
151 iowrite32_native(0x01000001, map
+ 0x000004);
153 /* read boot0 and strapping information */
154 boot0
= ioread32_native(map
+ 0x000000);
155 strap
= ioread32_native(map
+ 0x101000);
158 /* determine chipset and derive architecture from it */
159 if ((boot0
& 0x0f000000) > 0) {
160 device
->chipset
= (boot0
& 0xff00000) >> 20;
161 switch (device
->chipset
& 0xf0) {
162 case 0x10: device
->card_type
= NV_10
; break;
163 case 0x20: device
->card_type
= NV_20
; break;
164 case 0x30: device
->card_type
= NV_30
; break;
166 case 0x60: device
->card_type
= NV_40
; break;
170 case 0xa0: device
->card_type
= NV_50
; break;
171 case 0xc0: device
->card_type
= NV_C0
; break;
172 case 0xd0: device
->card_type
= NV_D0
; break;
173 case 0xe0: device
->card_type
= NV_E0
; break;
178 if ((boot0
& 0xff00fff0) == 0x20004000) {
179 if (boot0
& 0x00f00000)
180 device
->chipset
= 0x05;
182 device
->chipset
= 0x04;
183 device
->card_type
= NV_04
;
186 switch (device
->card_type
) {
187 case NV_04
: ret
= nv04_identify(device
); break;
188 case NV_10
: ret
= nv10_identify(device
); break;
189 case NV_20
: ret
= nv20_identify(device
); break;
190 case NV_30
: ret
= nv30_identify(device
); break;
191 case NV_40
: ret
= nv40_identify(device
); break;
192 case NV_50
: ret
= nv50_identify(device
); break;
194 case NV_D0
: ret
= nvc0_identify(device
); break;
195 case NV_E0
: ret
= nve0_identify(device
); break;
202 nv_error(device
, "unknown chipset, 0x%08x\n", boot0
);
206 nv_info(device
, "BOOT0 : 0x%08x\n", boot0
);
207 nv_info(device
, "Chipset: NV%02X\n", device
->chipset
);
208 nv_info(device
, "Family : NV%02X\n", device
->card_type
);
210 /* determine frequency of timing crystal */
211 if ( device
->chipset
< 0x17 ||
212 (device
->chipset
>= 0x20 && device
->chipset
<= 0x25))
218 case 0x00000000: device
->crystal
= 13500; break;
219 case 0x00000040: device
->crystal
= 14318; break;
220 case 0x00400000: device
->crystal
= 27000; break;
221 case 0x00400040: device
->crystal
= 25000; break;
224 nv_debug(device
, "crystal freq: %dKHz\n", device
->crystal
);
227 if (!(args
->disable
& NV_DEVICE_DISABLE_MMIO
) &&
228 !nv_subdev(device
)->mmio
) {
229 nv_subdev(device
)->mmio
= ioremap(mmio_base
, mmio_size
);
230 if (!nv_subdev(device
)->mmio
) {
231 nv_error(device
, "unable to map device registers\n");
236 /* ensure requested subsystems are available for use */
237 for (i
= 0; i
< NVDEV_SUBDEV_NR
; i
++) {
238 if (!(oclass
= device
->oclass
[i
]) || (disable
& (1ULL << i
)))
241 if (!device
->subdev
[i
]) {
242 ret
= nouveau_object_ctor(nv_object(device
), NULL
,
243 oclass
, NULL
, i
, &subdev
);
249 if (nv_iclass(subdev
, NV_ENGINE_CLASS
))
250 nouveau_subdev_reset(subdev
);
252 nouveau_object_ref(device
->subdev
[i
], &subdev
);
255 if (!nv_iclass(subdev
, NV_ENGINE_CLASS
)) {
256 ret
= nouveau_object_inc(subdev
);
258 nouveau_object_ref(NULL
, &subdev
);
263 nouveau_object_ref(subdev
, &devobj
->subdev
[i
]);
264 nouveau_object_ref(NULL
, &subdev
);
271 nouveau_devobj_dtor(struct nouveau_object
*object
)
273 struct nouveau_devobj
*devobj
= (void *)object
;
276 for (i
= NVDEV_SUBDEV_NR
- 1; i
>= 0; i
--)
277 nouveau_object_ref(NULL
, &devobj
->subdev
[i
]);
279 nouveau_parent_destroy(&devobj
->base
);
283 nouveau_devobj_init(struct nouveau_object
*object
)
285 struct nouveau_devobj
*devobj
= (void *)object
;
286 struct nouveau_object
*subdev
;
289 ret
= nouveau_parent_init(&devobj
->base
);
293 for (i
= 0; devobj
->created
&& i
< NVDEV_SUBDEV_NR
; i
++) {
294 if ((subdev
= devobj
->subdev
[i
])) {
295 if (!nv_iclass(subdev
, NV_ENGINE_CLASS
)) {
296 ret
= nouveau_object_inc(subdev
);
303 devobj
->created
= true;
307 for (--i
; i
>= 0; i
--) {
308 if ((subdev
= devobj
->subdev
[i
])) {
309 if (!nv_iclass(subdev
, NV_ENGINE_CLASS
))
310 nouveau_object_dec(subdev
, false);
318 nouveau_devobj_fini(struct nouveau_object
*object
, bool suspend
)
320 struct nouveau_devobj
*devobj
= (void *)object
;
321 struct nouveau_object
*subdev
;
324 for (i
= NVDEV_SUBDEV_NR
- 1; i
>= 0; i
--) {
325 if ((subdev
= devobj
->subdev
[i
])) {
326 if (!nv_iclass(subdev
, NV_ENGINE_CLASS
)) {
327 ret
= nouveau_object_dec(subdev
, suspend
);
334 ret
= nouveau_parent_fini(&devobj
->base
, suspend
);
336 for (; ret
&& suspend
&& i
< NVDEV_SUBDEV_NR
; i
++) {
337 if ((subdev
= devobj
->subdev
[i
])) {
338 if (!nv_iclass(subdev
, NV_ENGINE_CLASS
)) {
339 ret
= nouveau_object_inc(subdev
);
351 nouveau_devobj_rd08(struct nouveau_object
*object
, u32 addr
)
353 return nv_rd08(object
->engine
, addr
);
357 nouveau_devobj_rd16(struct nouveau_object
*object
, u32 addr
)
359 return nv_rd16(object
->engine
, addr
);
363 nouveau_devobj_rd32(struct nouveau_object
*object
, u32 addr
)
365 return nv_rd32(object
->engine
, addr
);
369 nouveau_devobj_wr08(struct nouveau_object
*object
, u32 addr
, u8 data
)
371 nv_wr08(object
->engine
, addr
, data
);
375 nouveau_devobj_wr16(struct nouveau_object
*object
, u32 addr
, u16 data
)
377 nv_wr16(object
->engine
, addr
, data
);
381 nouveau_devobj_wr32(struct nouveau_object
*object
, u32 addr
, u32 data
)
383 nv_wr32(object
->engine
, addr
, data
);
386 static struct nouveau_ofuncs
387 nouveau_devobj_ofuncs
= {
388 .ctor
= nouveau_devobj_ctor
,
389 .dtor
= nouveau_devobj_dtor
,
390 .init
= nouveau_devobj_init
,
391 .fini
= nouveau_devobj_fini
,
392 .rd08
= nouveau_devobj_rd08
,
393 .rd16
= nouveau_devobj_rd16
,
394 .rd32
= nouveau_devobj_rd32
,
395 .wr08
= nouveau_devobj_wr08
,
396 .wr16
= nouveau_devobj_wr16
,
397 .wr32
= nouveau_devobj_wr32
,
400 /******************************************************************************
401 * nouveau_device: engine functions
402 *****************************************************************************/
403 struct nouveau_oclass
404 nouveau_device_sclass
[] = {
405 { 0x0080, &nouveau_devobj_ofuncs
},
410 nouveau_device_dtor(struct nouveau_object
*object
)
412 struct nouveau_device
*device
= (void *)object
;
414 mutex_lock(&nv_devices_mutex
);
415 list_del(&device
->head
);
416 mutex_unlock(&nv_devices_mutex
);
418 if (device
->base
.mmio
)
419 iounmap(device
->base
.mmio
);
421 nouveau_subdev_destroy(&device
->base
);
424 static struct nouveau_oclass
425 nouveau_device_oclass
= {
426 .handle
= NV_SUBDEV(DEVICE
, 0x00),
427 .ofuncs
= &(struct nouveau_ofuncs
) {
428 .dtor
= nouveau_device_dtor
,
433 nouveau_device_create_(struct pci_dev
*pdev
, u64 name
, const char *sname
,
434 const char *cfg
, const char *dbg
,
435 int length
, void **pobject
)
437 struct nouveau_device
*device
;
440 mutex_lock(&nv_devices_mutex
);
441 list_for_each_entry(device
, &nv_devices
, head
) {
442 if (device
->handle
== name
)
446 ret
= nouveau_subdev_create_(NULL
, NULL
, &nouveau_device_oclass
, 0,
447 "DEVICE", "device", length
, pobject
);
452 atomic_set(&nv_object(device
)->usecount
, 2);
454 device
->handle
= name
;
455 device
->cfgopt
= cfg
;
456 device
->dbgopt
= dbg
;
457 device
->name
= sname
;
459 nv_subdev(device
)->debug
= nouveau_dbgopt(device
->dbgopt
, "DEVICE");
460 list_add(&device
->head
, &nv_devices
);
462 mutex_unlock(&nv_devices_mutex
);