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 nv50_instmem(p) container_of((p), struct nv50_instmem, base)
27 #include <core/memory.h>
28 #include <subdev/bar.h>
29 #include <subdev/fb.h>
30 #include <subdev/mmu.h>
33 struct nvkm_instmem base
;
34 unsigned long lock_flags
;
39 /******************************************************************************
40 * instmem object implementation
41 *****************************************************************************/
42 #define nv50_instobj(p) container_of((p), struct nv50_instobj, memory)
45 struct nvkm_memory memory
;
46 struct nv50_instmem
*imem
;
52 static enum nvkm_memory_target
53 nv50_instobj_target(struct nvkm_memory
*memory
)
55 return NVKM_MEM_TARGET_VRAM
;
59 nv50_instobj_addr(struct nvkm_memory
*memory
)
61 return nv50_instobj(memory
)->mem
->offset
;
65 nv50_instobj_size(struct nvkm_memory
*memory
)
67 return (u64
)nv50_instobj(memory
)->mem
->size
<< NVKM_RAM_MM_SHIFT
;
71 nv50_instobj_boot(struct nvkm_memory
*memory
, struct nvkm_vm
*vm
)
73 struct nv50_instobj
*iobj
= nv50_instobj(memory
);
74 struct nvkm_subdev
*subdev
= &iobj
->imem
->base
.subdev
;
75 struct nvkm_device
*device
= subdev
->device
;
76 u64 size
= nvkm_memory_size(memory
);
80 iobj
->map
= ERR_PTR(-ENOMEM
);
82 ret
= nvkm_vm_get(vm
, size
, 12, NV_MEM_ACCESS_RW
, &iobj
->bar
);
84 map
= ioremap(device
->func
->resource_addr(device
, 3) +
85 (u32
)iobj
->bar
.offset
, size
);
87 nvkm_memory_map(memory
, &iobj
->bar
, 0);
90 nvkm_warn(subdev
, "PRAMIN ioremap failed\n");
91 nvkm_vm_put(&iobj
->bar
);
94 nvkm_warn(subdev
, "PRAMIN exhausted\n");
99 nv50_instobj_release(struct nvkm_memory
*memory
)
101 struct nv50_instmem
*imem
= nv50_instobj(memory
)->imem
;
102 spin_unlock_irqrestore(&imem
->lock
, imem
->lock_flags
);
105 static void __iomem
*
106 nv50_instobj_acquire(struct nvkm_memory
*memory
)
108 struct nv50_instobj
*iobj
= nv50_instobj(memory
);
109 struct nv50_instmem
*imem
= iobj
->imem
;
110 struct nvkm_bar
*bar
= imem
->base
.subdev
.device
->bar
;
114 if (!iobj
->map
&& (vm
= nvkm_bar_kmap(bar
)))
115 nvkm_memory_boot(memory
, vm
);
116 if (!IS_ERR_OR_NULL(iobj
->map
))
119 spin_lock_irqsave(&imem
->lock
, flags
);
120 imem
->lock_flags
= flags
;
125 nv50_instobj_rd32(struct nvkm_memory
*memory
, u64 offset
)
127 struct nv50_instobj
*iobj
= nv50_instobj(memory
);
128 struct nv50_instmem
*imem
= iobj
->imem
;
129 struct nvkm_device
*device
= imem
->base
.subdev
.device
;
130 u64 base
= (iobj
->mem
->offset
+ offset
) & 0xffffff00000ULL
;
131 u64 addr
= (iobj
->mem
->offset
+ offset
) & 0x000000fffffULL
;
134 if (unlikely(imem
->addr
!= base
)) {
135 nvkm_wr32(device
, 0x001700, base
>> 16);
138 data
= nvkm_rd32(device
, 0x700000 + addr
);
143 nv50_instobj_wr32(struct nvkm_memory
*memory
, u64 offset
, u32 data
)
145 struct nv50_instobj
*iobj
= nv50_instobj(memory
);
146 struct nv50_instmem
*imem
= iobj
->imem
;
147 struct nvkm_device
*device
= imem
->base
.subdev
.device
;
148 u64 base
= (iobj
->mem
->offset
+ offset
) & 0xffffff00000ULL
;
149 u64 addr
= (iobj
->mem
->offset
+ offset
) & 0x000000fffffULL
;
151 if (unlikely(imem
->addr
!= base
)) {
152 nvkm_wr32(device
, 0x001700, base
>> 16);
155 nvkm_wr32(device
, 0x700000 + addr
, data
);
159 nv50_instobj_map(struct nvkm_memory
*memory
, struct nvkm_vma
*vma
, u64 offset
)
161 struct nv50_instobj
*iobj
= nv50_instobj(memory
);
162 nvkm_vm_map_at(vma
, offset
, iobj
->mem
);
166 nv50_instobj_dtor(struct nvkm_memory
*memory
)
168 struct nv50_instobj
*iobj
= nv50_instobj(memory
);
169 struct nvkm_ram
*ram
= iobj
->imem
->base
.subdev
.device
->fb
->ram
;
170 if (!IS_ERR_OR_NULL(iobj
->map
)) {
171 nvkm_vm_put(&iobj
->bar
);
174 ram
->func
->put(ram
, &iobj
->mem
);
178 static const struct nvkm_memory_func
179 nv50_instobj_func
= {
180 .dtor
= nv50_instobj_dtor
,
181 .target
= nv50_instobj_target
,
182 .size
= nv50_instobj_size
,
183 .addr
= nv50_instobj_addr
,
184 .boot
= nv50_instobj_boot
,
185 .acquire
= nv50_instobj_acquire
,
186 .release
= nv50_instobj_release
,
187 .rd32
= nv50_instobj_rd32
,
188 .wr32
= nv50_instobj_wr32
,
189 .map
= nv50_instobj_map
,
193 nv50_instobj_new(struct nvkm_instmem
*base
, u32 size
, u32 align
, bool zero
,
194 struct nvkm_memory
**pmemory
)
196 struct nv50_instmem
*imem
= nv50_instmem(base
);
197 struct nv50_instobj
*iobj
;
198 struct nvkm_ram
*ram
= imem
->base
.subdev
.device
->fb
->ram
;
201 if (!(iobj
= kzalloc(sizeof(*iobj
), GFP_KERNEL
)))
203 *pmemory
= &iobj
->memory
;
205 nvkm_memory_ctor(&nv50_instobj_func
, &iobj
->memory
);
208 size
= max((size
+ 4095) & ~4095, (u32
)4096);
209 align
= max((align
+ 4095) & ~4095, (u32
)4096);
211 ret
= ram
->func
->get(ram
, size
, align
, 0, 0x800, &iobj
->mem
);
215 iobj
->mem
->page_shift
= 12;
219 /******************************************************************************
220 * instmem subdev implementation
221 *****************************************************************************/
224 nv50_instmem_fini(struct nvkm_instmem
*base
)
226 nv50_instmem(base
)->addr
= ~0ULL;
229 static const struct nvkm_instmem_func
231 .fini
= nv50_instmem_fini
,
232 .memory_new
= nv50_instobj_new
,
238 nv50_instmem_new(struct nvkm_device
*device
, int index
,
239 struct nvkm_instmem
**pimem
)
241 struct nv50_instmem
*imem
;
243 if (!(imem
= kzalloc(sizeof(*imem
), GFP_KERNEL
)))
245 nvkm_instmem_ctor(&nv50_instmem
, device
, index
, &imem
->base
);
246 spin_lock_init(&imem
->lock
);
247 *pimem
= &imem
->base
;