File Index
Files and directories
Sign in
FILE

nv50.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c C
  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 */
 24#include "nv50.h"
 25
 26#include <core/gpuobj.h>
 27#include <subdev/fb.h>
 28#include <subdev/mmu.h>
 29#include <subdev/timer.h>
 30
 31static void
 32nv50_bar_flush(struct nvkm_bar *base)
 33{
 34	struct nv50_bar *bar = nv50_bar(base);
 35	struct nvkm_device *device = bar->base.subdev.device;
 36	unsigned long flags;
 37	spin_lock_irqsave(&bar->base.lock, flags);
 38	nvkm_wr32(device, 0x00330c, 0x00000001);
 39	nvkm_msec(device, 2000,
 40		if (!(nvkm_rd32(device, 0x00330c) & 0x00000002))
 41			break;
 42	);
 43	spin_unlock_irqrestore(&bar->base.lock, flags);
 44}
 45
 46struct nvkm_vmm *
 47nv50_bar_bar1_vmm(struct nvkm_bar *base)
 48{
 49	return nv50_bar(base)->bar1_vmm;
 50}
 51
 52void
 53nv50_bar_bar1_wait(struct nvkm_bar *base)
 54{
 55	nvkm_bar_flush(base);
 56}
 57
 58void
 59nv50_bar_bar1_fini(struct nvkm_bar *bar)
 60{
 61	nvkm_wr32(bar->subdev.device, 0x001708, 0x00000000);
 62}
 63
 64void
 65nv50_bar_bar1_init(struct nvkm_bar *base)
 66{
 67	struct nvkm_device *device = base->subdev.device;
 68	struct nv50_bar *bar = nv50_bar(base);
 69	nvkm_wr32(device, 0x001708, 0x80000000 | bar->bar1->node->offset >> 4);
 70}
 71
 72struct nvkm_vmm *
 73nv50_bar_bar2_vmm(struct nvkm_bar *base)
 74{
 75	return nv50_bar(base)->bar2_vmm;
 76}
 77
 78void
 79nv50_bar_bar2_fini(struct nvkm_bar *bar)
 80{
 81	nvkm_wr32(bar->subdev.device, 0x00170c, 0x00000000);
 82}
 83
 84void
 85nv50_bar_bar2_init(struct nvkm_bar *base)
 86{
 87	struct nvkm_device *device = base->subdev.device;
 88	struct nv50_bar *bar = nv50_bar(base);
 89	nvkm_wr32(device, 0x001704, 0x00000000 | bar->mem->addr >> 12);
 90	nvkm_wr32(device, 0x001704, 0x40000000 | bar->mem->addr >> 12);
 91	nvkm_wr32(device, 0x00170c, 0x80000000 | bar->bar2->node->offset >> 4);
 92}
 93
 94void
 95nv50_bar_init(struct nvkm_bar *base)
 96{
 97	struct nv50_bar *bar = nv50_bar(base);
 98	struct nvkm_device *device = bar->base.subdev.device;
 99	int i;
100
101	for (i = 0; i < 8; i++)
102		nvkm_wr32(device, 0x001900 + (i * 4), 0x00000000);
103}
104
105int
106nv50_bar_oneinit(struct nvkm_bar *base)
107{
108	struct nv50_bar *bar = nv50_bar(base);
109	struct nvkm_device *device = bar->base.subdev.device;
110	static struct lock_class_key bar1_lock;
111	static struct lock_class_key bar2_lock;
112	u64 start, limit, size;
113	int ret;
114
115	ret = nvkm_gpuobj_new(device, 0x20000, 0, false, NULL, &bar->mem);
116	if (ret)
117		return ret;
118
119	ret = nvkm_gpuobj_new(device, bar->pgd_addr, 0, false, bar->mem,
120			      &bar->pad);
121	if (ret)
122		return ret;
123
124	ret = nvkm_gpuobj_new(device, 0x4000, 0, false, bar->mem, &bar->pgd);
125	if (ret)
126		return ret;
127
128	/* BAR2 */
129	start = 0x0100000000ULL;
130	size = device->func->resource_size(device, NVKM_BAR2_INST);
131	if (!size)
132		return -ENOMEM;
133	limit = start + size;
134
135	ret = nvkm_vmm_new(device, start, limit-- - start, NULL, 0,
136			   &bar2_lock, "bar2", &bar->bar2_vmm);
137	if (ret)
138		return ret;
139
140	atomic_inc(&bar->bar2_vmm->engref[NVKM_SUBDEV_BAR]);
141	bar->bar2_vmm->debug = bar->base.subdev.debug;
142
143	ret = nvkm_vmm_boot(bar->bar2_vmm);
144	if (ret)
145		return ret;
146
147	ret = nvkm_vmm_join(bar->bar2_vmm, bar->mem->memory);
148	if (ret)
149		return ret;
150
151	ret = nvkm_gpuobj_new(device, 24, 16, false, bar->mem, &bar->bar2);
152	if (ret)
153		return ret;
154
155	nvkm_kmap(bar->bar2);
156	nvkm_wo32(bar->bar2, 0x00, 0x7fc00000);
157	nvkm_wo32(bar->bar2, 0x04, lower_32_bits(limit));
158	nvkm_wo32(bar->bar2, 0x08, lower_32_bits(start));
159	nvkm_wo32(bar->bar2, 0x0c, upper_32_bits(limit) << 24 |
160				   upper_32_bits(start));
161	nvkm_wo32(bar->bar2, 0x10, 0x00000000);
162	nvkm_wo32(bar->bar2, 0x14, 0x00000000);
163	nvkm_done(bar->bar2);
164
165	bar->base.subdev.oneinit = true;
166	nvkm_bar_bar2_init(device);
167
168	/* BAR1 */
169	start = 0x0000000000ULL;
170	size = device->func->resource_size(device, NVKM_BAR1_FB);
171	if (!size)
172		return -ENOMEM;
173	limit = start + size;
174
175	ret = nvkm_vmm_new(device, start, limit-- - start, NULL, 0,
176			   &bar1_lock, "bar1", &bar->bar1_vmm);
177	if (ret)
178		return ret;
179
180	atomic_inc(&bar->bar1_vmm->engref[NVKM_SUBDEV_BAR]);
181	bar->bar1_vmm->debug = bar->base.subdev.debug;
182
183	ret = nvkm_vmm_join(bar->bar1_vmm, bar->mem->memory);
184	if (ret)
185		return ret;
186
187	ret = nvkm_gpuobj_new(device, 24, 16, false, bar->mem, &bar->bar1);
188	if (ret)
189		return ret;
190
191	nvkm_kmap(bar->bar1);
192	nvkm_wo32(bar->bar1, 0x00, 0x7fc00000);
193	nvkm_wo32(bar->bar1, 0x04, lower_32_bits(limit));
194	nvkm_wo32(bar->bar1, 0x08, lower_32_bits(start));
195	nvkm_wo32(bar->bar1, 0x0c, upper_32_bits(limit) << 24 |
196				   upper_32_bits(start));
197	nvkm_wo32(bar->bar1, 0x10, 0x00000000);
198	nvkm_wo32(bar->bar1, 0x14, 0x00000000);
199	nvkm_done(bar->bar1);
200	return 0;
201}
202
203void *
204nv50_bar_dtor(struct nvkm_bar *base)
205{
206	struct nv50_bar *bar = nv50_bar(base);
207	if (bar->mem) {
208		nvkm_gpuobj_del(&bar->bar1);
209		nvkm_vmm_part(bar->bar1_vmm, bar->mem->memory);
210		nvkm_vmm_unref(&bar->bar1_vmm);
211		nvkm_gpuobj_del(&bar->bar2);
212		nvkm_vmm_part(bar->bar2_vmm, bar->mem->memory);
213		nvkm_vmm_unref(&bar->bar2_vmm);
214		nvkm_gpuobj_del(&bar->pgd);
215		nvkm_gpuobj_del(&bar->pad);
216		nvkm_gpuobj_del(&bar->mem);
217	}
218	return bar;
219}
220
221int
222nv50_bar_new_(const struct nvkm_bar_func *func, struct nvkm_device *device,
223	      enum nvkm_subdev_type type, int inst, u32 pgd_addr, struct nvkm_bar **pbar)
224{
225	struct nv50_bar *bar;
226	if (!(bar = kzalloc(sizeof(*bar), GFP_KERNEL)))
227		return -ENOMEM;
228	nvkm_bar_ctor(func, device, type, inst, &bar->base);
229	bar->pgd_addr = pgd_addr;
230	*pbar = &bar->base;
231	return 0;
232}
233
234static const struct nvkm_bar_func
235nv50_bar_func = {
236	.dtor = nv50_bar_dtor,
237	.oneinit = nv50_bar_oneinit,
238	.init = nv50_bar_init,
239	.bar1.init = nv50_bar_bar1_init,
240	.bar1.fini = nv50_bar_bar1_fini,
241	.bar1.wait = nv50_bar_bar1_wait,
242	.bar1.vmm = nv50_bar_bar1_vmm,
243	.bar2.init = nv50_bar_bar2_init,
244	.bar2.fini = nv50_bar_bar2_fini,
245	.bar2.wait = nv50_bar_bar1_wait,
246	.bar2.vmm = nv50_bar_bar2_vmm,
247	.flush = nv50_bar_flush,
248};
249
250int
251nv50_bar_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
252	     struct nvkm_bar **pbar)
253{
254	return nv50_bar_new_(&nv50_bar_func, device, type, inst, 0x1400, pbar);
255}
~/ Read-only file preview.