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/gpuobj.h>
27 #include <subdev/timer.h>
28 #include <subdev/vm.h>
32 #define NV44_GART_SIZE (512 * 1024 * 1024)
33 #define NV44_GART_PAGE ( 4 * 1024)
35 /*******************************************************************************
36 * VM map/unmap callbacks
37 ******************************************************************************/
40 nv44_vm_flush_priv(struct nv04_vmmgr_priv
*priv
, u32 base
, u32 size
)
42 nv_wr32(priv
, 0x100814, (size
- 1) << 12);
43 nv_wr32(priv
, 0x100808, base
| 0x20);
44 if (!nv_wait(priv
, 0x100808, 0x00000001, 0x00000001))
45 nv_error(priv
, "timeout: 0x%08x\n", nv_rd32(priv
, 0x100808));
46 nv_wr32(priv
, 0x100808, 0x00000000);
50 nv44_vm_fill(struct nouveau_gpuobj
*pgt
, dma_addr_t null
,
51 dma_addr_t
*list
, u32 pte
, u32 cnt
)
53 u32 base
= (pte
<< 2) & ~0x0000000f;
56 tmp
[0] = nv_ro32(pgt
, base
+ 0x0);
57 tmp
[1] = nv_ro32(pgt
, base
+ 0x4);
58 tmp
[2] = nv_ro32(pgt
, base
+ 0x8);
59 tmp
[3] = nv_ro32(pgt
, base
+ 0xc);
61 u32 addr
= list
? (*list
++ >> 12) : (null
>> 12);
62 switch (pte
++ & 0x3) {
64 tmp
[0] &= ~0x07ffffff;
68 tmp
[0] &= ~0xf8000000;
70 tmp
[1] &= ~0x003fffff;
74 tmp
[1] &= ~0xffc00000;
76 tmp
[2] &= ~0x0001ffff;
80 tmp
[2] &= ~0xfffe0000;
82 tmp
[3] &= ~0x00000fff;
88 nv_wo32(pgt
, base
+ 0x0, tmp
[0]);
89 nv_wo32(pgt
, base
+ 0x4, tmp
[1]);
90 nv_wo32(pgt
, base
+ 0x8, tmp
[2]);
91 nv_wo32(pgt
, base
+ 0xc, tmp
[3] | 0x40000000);
95 nv44_vm_map_sg(struct nouveau_vma
*vma
, struct nouveau_gpuobj
*pgt
,
96 struct nouveau_mem
*mem
, u32 pte
, u32 cnt
, dma_addr_t
*list
)
98 struct nv04_vmmgr_priv
*priv
= (void *)vma
->vm
->vmm
;
105 u32 max
= 4 - (pte
& 3);
106 u32 part
= (cnt
> max
) ? max
: cnt
;
107 nv44_vm_fill(pgt
, priv
->null
, list
, pte
, part
);
114 for (i
= 0; i
< 4; i
++)
115 tmp
[i
] = *list
++ >> 12;
116 nv_wo32(pgt
, pte
++ * 4, tmp
[0] >> 0 | tmp
[1] << 27);
117 nv_wo32(pgt
, pte
++ * 4, tmp
[1] >> 5 | tmp
[2] << 22);
118 nv_wo32(pgt
, pte
++ * 4, tmp
[2] >> 10 | tmp
[3] << 17);
119 nv_wo32(pgt
, pte
++ * 4, tmp
[3] >> 15 | 0x40000000);
124 nv44_vm_fill(pgt
, priv
->null
, list
, pte
, cnt
);
125 nv44_vm_flush_priv(priv
, base
, size
);
129 nv44_vm_unmap(struct nouveau_gpuobj
*pgt
, u32 pte
, u32 cnt
)
131 struct nv04_vmmgr_priv
*priv
= (void *)nouveau_vmmgr(pgt
);
132 u32 base
= pte
<< 12;
136 u32 max
= 4 - (pte
& 3);
137 u32 part
= (cnt
> max
) ? max
: cnt
;
138 nv44_vm_fill(pgt
, priv
->null
, NULL
, pte
, part
);
144 nv_wo32(pgt
, pte
++ * 4, 0x00000000);
145 nv_wo32(pgt
, pte
++ * 4, 0x00000000);
146 nv_wo32(pgt
, pte
++ * 4, 0x00000000);
147 nv_wo32(pgt
, pte
++ * 4, 0x00000000);
152 nv44_vm_fill(pgt
, priv
->null
, NULL
, pte
, cnt
);
153 nv44_vm_flush_priv(priv
, base
, size
);
157 nv44_vm_flush(struct nouveau_vm
*vm
)
161 /*******************************************************************************
163 ******************************************************************************/
166 nv44_vmmgr_ctor(struct nouveau_object
*parent
, struct nouveau_object
*engine
,
167 struct nouveau_oclass
*oclass
, void *data
, u32 size
,
168 struct nouveau_object
**pobject
)
170 struct nouveau_device
*device
= nv_device(parent
);
171 struct nv04_vmmgr_priv
*priv
;
174 ret
= nouveau_vmmgr_create(parent
, engine
, oclass
, "PCIEGART",
176 *pobject
= nv_object(priv
);
180 priv
->base
.create
= nv04_vm_create
;
181 priv
->base
.limit
= NV44_GART_SIZE
;
182 priv
->base
.pgt_bits
= 32 - 12;
183 priv
->base
.spg_shift
= 12;
184 priv
->base
.lpg_shift
= 12;
185 priv
->base
.map_sg
= nv44_vm_map_sg
;
186 priv
->base
.unmap
= nv44_vm_unmap
;
187 priv
->base
.flush
= nv44_vm_flush
;
189 priv
->page
= alloc_page(GFP_DMA32
| GFP_KERNEL
);
191 priv
->null
= pci_map_page(device
->pdev
, priv
->page
, 0,
192 PAGE_SIZE
, PCI_DMA_BIDIRECTIONAL
);
193 if (pci_dma_mapping_error(device
->pdev
, priv
->null
)) {
194 __free_page(priv
->page
);
201 nv_warn(priv
, "unable to allocate dummy page\n");
203 ret
= nouveau_vm_create(&priv
->base
, 0, NV44_GART_SIZE
, 0, 4096,
208 ret
= nouveau_gpuobj_new(parent
, NULL
,
209 (NV44_GART_SIZE
/ NV44_GART_PAGE
) * 4,
210 512 * 1024, NVOBJ_FLAG_ZERO_ALLOC
,
211 &priv
->vm
->pgt
[0].obj
[0]);
212 priv
->vm
->pgt
[0].refcount
[0] = 1;
220 nv44_vmmgr_init(struct nouveau_object
*object
)
222 struct nv04_vmmgr_priv
*priv
= (void *)object
;
223 struct nouveau_gpuobj
*gart
= priv
->vm
->pgt
[0].obj
[0];
227 ret
= nouveau_vmmgr_init(&priv
->base
);
231 /* calculate vram address of this PRAMIN block, object must be
232 * allocated on 512KiB alignment, and not exceed a total size
233 * of 512KiB for this to work correctly
235 addr
= nv_rd32(priv
, 0x10020c);
236 addr
-= ((gart
->addr
>> 19) + 1) << 19;
238 nv_wr32(priv
, 0x100850, 0x80000000);
239 nv_wr32(priv
, 0x100818, priv
->null
);
240 nv_wr32(priv
, 0x100804, NV44_GART_SIZE
);
241 nv_wr32(priv
, 0x100850, 0x00008000);
242 nv_mask(priv
, 0x10008c, 0x00000200, 0x00000200);
243 nv_wr32(priv
, 0x100820, 0x00000000);
244 nv_wr32(priv
, 0x10082c, 0x00000001);
245 nv_wr32(priv
, 0x100800, addr
| 0x00000010);
249 struct nouveau_oclass
250 nv44_vmmgr_oclass
= {
251 .handle
= NV_SUBDEV(VM
, 0x44),
252 .ofuncs
= &(struct nouveau_ofuncs
) {
253 .ctor
= nv44_vmmgr_ctor
,
254 .dtor
= nv04_vmmgr_dtor
,
255 .init
= nv44_vmmgr_init
,
256 .fini
= _nouveau_vmmgr_fini
,
This page took 0.039403 seconds and 5 git commands to generate.