]>
Commit | Line | Data |
---|---|---|
245dcfe9 BS |
1 | /* |
2 | * Copyright 2012 Red Hat Inc. | |
3 | * | |
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: | |
10 | * | |
11 | * The above copyright notice and this permission notice shall be included in | |
12 | * all copies or substantial portions of the Software. | |
13 | * | |
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. | |
21 | * | |
22 | * Authors: Ben Skeggs | |
23 | */ | |
32932281 | 24 | #include "gf100.h" |
245dcfe9 BS |
25 | |
26 | #include <core/gpuobj.h> | |
27 | #include <subdev/fb.h> | |
28 | #include <subdev/mmu.h> | |
29 | ||
d8e83994 | 30 | static struct nvkm_vm * |
32932281 | 31 | gf100_bar_kmap(struct nvkm_bar *base) |
245dcfe9 | 32 | { |
32932281 | 33 | return gf100_bar(base)->bar[0].vm; |
245dcfe9 BS |
34 | } |
35 | ||
32932281 BS |
36 | int |
37 | gf100_bar_umap(struct nvkm_bar *base, u64 size, int type, struct nvkm_vma *vma) | |
245dcfe9 | 38 | { |
32932281 | 39 | struct gf100_bar *bar = gf100_bar(base); |
d8e83994 | 40 | return nvkm_vm_get(bar->bar[1].vm, size, type, NV_MEM_ACCESS_RW, vma); |
245dcfe9 BS |
41 | } |
42 | ||
245dcfe9 | 43 | static int |
5b0c189f | 44 | gf100_bar_ctor_vm(struct gf100_bar *bar, struct gf100_bar_vm *bar_vm, |
1de68568 | 45 | struct lock_class_key *key, int bar_nr) |
245dcfe9 | 46 | { |
32932281 | 47 | struct nvkm_device *device = bar->base.subdev.device; |
245dcfe9 BS |
48 | struct nvkm_vm *vm; |
49 | resource_size_t bar_len; | |
50 | int ret; | |
51 | ||
adb53d27 | 52 | ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0, false, |
245dcfe9 BS |
53 | &bar_vm->mem); |
54 | if (ret) | |
55 | return ret; | |
56 | ||
f027f491 | 57 | ret = nvkm_gpuobj_new(device, 0x8000, 0, false, NULL, &bar_vm->pgd); |
245dcfe9 BS |
58 | if (ret) |
59 | return ret; | |
60 | ||
7e8820fe | 61 | bar_len = device->func->resource_size(device, bar_nr); |
245dcfe9 | 62 | |
1de68568 | 63 | ret = nvkm_vm_new(device, 0, bar_len, 0, key, &vm); |
245dcfe9 BS |
64 | if (ret) |
65 | return ret; | |
66 | ||
68f3f702 | 67 | atomic_inc(&vm->engref[NVKM_SUBDEV_BAR]); |
245dcfe9 BS |
68 | |
69 | /* | |
70 | * Bootstrap page table lookup. | |
71 | */ | |
72 | if (bar_nr == 3) { | |
d8e83994 | 73 | ret = nvkm_vm_boot(vm, bar_len); |
32932281 BS |
74 | if (ret) { |
75 | nvkm_vm_ref(NULL, &vm, NULL); | |
245dcfe9 | 76 | return ret; |
32932281 | 77 | } |
245dcfe9 BS |
78 | } |
79 | ||
80 | ret = nvkm_vm_ref(vm, &bar_vm->vm, bar_vm->pgd); | |
81 | nvkm_vm_ref(NULL, &vm, NULL); | |
82 | if (ret) | |
83 | return ret; | |
84 | ||
19187075 BS |
85 | nvkm_kmap(bar_vm->mem); |
86 | nvkm_wo32(bar_vm->mem, 0x0200, lower_32_bits(bar_vm->pgd->addr)); | |
87 | nvkm_wo32(bar_vm->mem, 0x0204, upper_32_bits(bar_vm->pgd->addr)); | |
88 | nvkm_wo32(bar_vm->mem, 0x0208, lower_32_bits(bar_len - 1)); | |
89 | nvkm_wo32(bar_vm->mem, 0x020c, upper_32_bits(bar_len - 1)); | |
90 | nvkm_done(bar_vm->mem); | |
245dcfe9 BS |
91 | return 0; |
92 | } | |
93 | ||
94 | int | |
32932281 | 95 | gf100_bar_oneinit(struct nvkm_bar *base) |
245dcfe9 | 96 | { |
1de68568 BS |
97 | static struct lock_class_key bar1_lock; |
98 | static struct lock_class_key bar3_lock; | |
32932281 | 99 | struct gf100_bar *bar = gf100_bar(base); |
245dcfe9 BS |
100 | int ret; |
101 | ||
245dcfe9 | 102 | /* BAR3 */ |
32932281 | 103 | if (bar->base.func->kmap) { |
1de68568 | 104 | ret = gf100_bar_ctor_vm(bar, &bar->bar[0], &bar3_lock, 3); |
245dcfe9 BS |
105 | if (ret) |
106 | return ret; | |
107 | } | |
108 | ||
109 | /* BAR1 */ | |
1de68568 | 110 | ret = gf100_bar_ctor_vm(bar, &bar->bar[1], &bar1_lock, 1); |
245dcfe9 BS |
111 | if (ret) |
112 | return ret; | |
113 | ||
245dcfe9 BS |
114 | return 0; |
115 | } | |
116 | ||
245dcfe9 | 117 | int |
32932281 | 118 | gf100_bar_init(struct nvkm_bar *base) |
245dcfe9 | 119 | { |
32932281 | 120 | struct gf100_bar *bar = gf100_bar(base); |
9155c162 | 121 | struct nvkm_device *device = bar->base.subdev.device; |
adb53d27 | 122 | u32 addr; |
245dcfe9 | 123 | |
9155c162 BS |
124 | nvkm_mask(device, 0x000200, 0x00000100, 0x00000000); |
125 | nvkm_mask(device, 0x000200, 0x00000100, 0x00000100); | |
245dcfe9 | 126 | |
adb53d27 BS |
127 | addr = nvkm_memory_addr(bar->bar[1].mem) >> 12; |
128 | nvkm_wr32(device, 0x001704, 0x80000000 | addr); | |
129 | ||
130 | if (bar->bar[0].mem) { | |
131 | addr = nvkm_memory_addr(bar->bar[0].mem) >> 12; | |
38bcb208 | 132 | nvkm_wr32(device, 0x001714, 0x80000000 | addr); |
adb53d27 BS |
133 | } |
134 | ||
245dcfe9 BS |
135 | return 0; |
136 | } | |
137 | ||
32932281 BS |
138 | void * |
139 | gf100_bar_dtor(struct nvkm_bar *base) | |
140 | { | |
141 | struct gf100_bar *bar = gf100_bar(base); | |
142 | ||
143 | nvkm_vm_ref(NULL, &bar->bar[1].vm, bar->bar[1].pgd); | |
144 | nvkm_gpuobj_del(&bar->bar[1].pgd); | |
145 | nvkm_memory_del(&bar->bar[1].mem); | |
146 | ||
147 | if (bar->bar[0].vm) { | |
148 | nvkm_memory_del(&bar->bar[0].vm->pgt[0].mem[0]); | |
149 | nvkm_vm_ref(NULL, &bar->bar[0].vm, bar->bar[0].pgd); | |
150 | } | |
151 | nvkm_gpuobj_del(&bar->bar[0].pgd); | |
152 | nvkm_memory_del(&bar->bar[0].mem); | |
153 | return bar; | |
154 | } | |
155 | ||
156 | int | |
157 | gf100_bar_new_(const struct nvkm_bar_func *func, struct nvkm_device *device, | |
158 | int index, struct nvkm_bar **pbar) | |
159 | { | |
160 | struct gf100_bar *bar; | |
161 | if (!(bar = kzalloc(sizeof(*bar), GFP_KERNEL))) | |
162 | return -ENOMEM; | |
163 | nvkm_bar_ctor(func, device, index, &bar->base); | |
164 | *pbar = &bar->base; | |
165 | return 0; | |
166 | } | |
167 | ||
168 | static const struct nvkm_bar_func | |
169 | gf100_bar_func = { | |
170 | .dtor = gf100_bar_dtor, | |
171 | .oneinit = gf100_bar_oneinit, | |
172 | .init = gf100_bar_init, | |
173 | .kmap = gf100_bar_kmap, | |
174 | .umap = gf100_bar_umap, | |
175 | .flush = g84_bar_flush, | |
245dcfe9 | 176 | }; |
32932281 BS |
177 | |
178 | int | |
179 | gf100_bar_new(struct nvkm_device *device, int index, struct nvkm_bar **pbar) | |
180 | { | |
181 | return gf100_bar_new_(&gf100_bar_func, device, index, pbar); | |
182 | } |