1*149bda8eSriastradh /*	$NetBSD: nouveau_nvkm_core_subdev.c,v 1.5 2021/12/19 11:34:44 riastradh Exp $	*/
2d350ecf5Sriastradh 
3d350ecf5Sriastradh /*
4d350ecf5Sriastradh  * Copyright 2012 Red Hat Inc.
5d350ecf5Sriastradh  *
6d350ecf5Sriastradh  * Permission is hereby granted, free of charge, to any person obtaining a
7d350ecf5Sriastradh  * copy of this software and associated documentation files (the "Software"),
8d350ecf5Sriastradh  * to deal in the Software without restriction, including without limitation
9d350ecf5Sriastradh  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10d350ecf5Sriastradh  * and/or sell copies of the Software, and to permit persons to whom the
11d350ecf5Sriastradh  * Software is furnished to do so, subject to the following conditions:
12d350ecf5Sriastradh  *
13d350ecf5Sriastradh  * The above copyright notice and this permission notice shall be included in
14d350ecf5Sriastradh  * all copies or substantial portions of the Software.
15d350ecf5Sriastradh  *
16d350ecf5Sriastradh  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17d350ecf5Sriastradh  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18d350ecf5Sriastradh  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19d350ecf5Sriastradh  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20d350ecf5Sriastradh  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21d350ecf5Sriastradh  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22d350ecf5Sriastradh  * OTHER DEALINGS IN THE SOFTWARE.
23d350ecf5Sriastradh  *
24d350ecf5Sriastradh  * Authors: Ben Skeggs
25d350ecf5Sriastradh  */
26d350ecf5Sriastradh #include <sys/cdefs.h>
27*149bda8eSriastradh __KERNEL_RCSID(0, "$NetBSD: nouveau_nvkm_core_subdev.c,v 1.5 2021/12/19 11:34:44 riastradh Exp $");
28d350ecf5Sriastradh 
29d350ecf5Sriastradh #include <core/subdev.h>
30d350ecf5Sriastradh #include <core/device.h>
31d350ecf5Sriastradh #include <core/option.h>
32677dec6eSriastradh #include <subdev/mc.h>
33d350ecf5Sriastradh 
34*149bda8eSriastradh #include <linux/nbsd-namespace.h>
35*149bda8eSriastradh 
36d350ecf5Sriastradh static struct lock_class_key nvkm_subdev_lock_class[NVKM_SUBDEV_NR];
37d350ecf5Sriastradh 
38d350ecf5Sriastradh const char *
39d350ecf5Sriastradh nvkm_subdev_name[NVKM_SUBDEV_NR] = {
40677dec6eSriastradh 	[NVKM_SUBDEV_ACR     ] = "acr",
41d350ecf5Sriastradh 	[NVKM_SUBDEV_BAR     ] = "bar",
42d350ecf5Sriastradh 	[NVKM_SUBDEV_VBIOS   ] = "bios",
43d350ecf5Sriastradh 	[NVKM_SUBDEV_BUS     ] = "bus",
44d350ecf5Sriastradh 	[NVKM_SUBDEV_CLK     ] = "clk",
45d350ecf5Sriastradh 	[NVKM_SUBDEV_DEVINIT ] = "devinit",
46677dec6eSriastradh 	[NVKM_SUBDEV_FAULT   ] = "fault",
47d350ecf5Sriastradh 	[NVKM_SUBDEV_FB      ] = "fb",
48d350ecf5Sriastradh 	[NVKM_SUBDEV_FUSE    ] = "fuse",
49d350ecf5Sriastradh 	[NVKM_SUBDEV_GPIO    ] = "gpio",
50677dec6eSriastradh 	[NVKM_SUBDEV_GSP     ] = "gsp",
51d350ecf5Sriastradh 	[NVKM_SUBDEV_I2C     ] = "i2c",
52d350ecf5Sriastradh 	[NVKM_SUBDEV_IBUS    ] = "priv",
53677dec6eSriastradh 	[NVKM_SUBDEV_ICCSENSE] = "iccsense",
54d350ecf5Sriastradh 	[NVKM_SUBDEV_INSTMEM ] = "imem",
55d350ecf5Sriastradh 	[NVKM_SUBDEV_LTC     ] = "ltc",
56d350ecf5Sriastradh 	[NVKM_SUBDEV_MC      ] = "mc",
57d350ecf5Sriastradh 	[NVKM_SUBDEV_MMU     ] = "mmu",
58d350ecf5Sriastradh 	[NVKM_SUBDEV_MXM     ] = "mxm",
59d350ecf5Sriastradh 	[NVKM_SUBDEV_PCI     ] = "pci",
60d350ecf5Sriastradh 	[NVKM_SUBDEV_PMU     ] = "pmu",
61d350ecf5Sriastradh 	[NVKM_SUBDEV_THERM   ] = "therm",
62d350ecf5Sriastradh 	[NVKM_SUBDEV_TIMER   ] = "tmr",
63677dec6eSriastradh 	[NVKM_SUBDEV_TOP     ] = "top",
64d350ecf5Sriastradh 	[NVKM_SUBDEV_VOLT    ] = "volt",
65d350ecf5Sriastradh 	[NVKM_ENGINE_BSP     ] = "bsp",
66d350ecf5Sriastradh 	[NVKM_ENGINE_CE0     ] = "ce0",
67d350ecf5Sriastradh 	[NVKM_ENGINE_CE1     ] = "ce1",
68d350ecf5Sriastradh 	[NVKM_ENGINE_CE2     ] = "ce2",
69677dec6eSriastradh 	[NVKM_ENGINE_CE3     ] = "ce3",
70677dec6eSriastradh 	[NVKM_ENGINE_CE4     ] = "ce4",
71677dec6eSriastradh 	[NVKM_ENGINE_CE5     ] = "ce5",
72677dec6eSriastradh 	[NVKM_ENGINE_CE6     ] = "ce6",
73677dec6eSriastradh 	[NVKM_ENGINE_CE7     ] = "ce7",
74677dec6eSriastradh 	[NVKM_ENGINE_CE8     ] = "ce8",
75d350ecf5Sriastradh 	[NVKM_ENGINE_CIPHER  ] = "cipher",
76d350ecf5Sriastradh 	[NVKM_ENGINE_DISP    ] = "disp",
77d350ecf5Sriastradh 	[NVKM_ENGINE_DMAOBJ  ] = "dma",
78d350ecf5Sriastradh 	[NVKM_ENGINE_FIFO    ] = "fifo",
79d350ecf5Sriastradh 	[NVKM_ENGINE_GR      ] = "gr",
80d350ecf5Sriastradh 	[NVKM_ENGINE_IFB     ] = "ifb",
81d350ecf5Sriastradh 	[NVKM_ENGINE_ME      ] = "me",
82d350ecf5Sriastradh 	[NVKM_ENGINE_MPEG    ] = "mpeg",
83d350ecf5Sriastradh 	[NVKM_ENGINE_MSENC   ] = "msenc",
84d350ecf5Sriastradh 	[NVKM_ENGINE_MSPDEC  ] = "mspdec",
85d350ecf5Sriastradh 	[NVKM_ENGINE_MSPPP   ] = "msppp",
86d350ecf5Sriastradh 	[NVKM_ENGINE_MSVLD   ] = "msvld",
87677dec6eSriastradh 	[NVKM_ENGINE_NVENC0  ] = "nvenc0",
88677dec6eSriastradh 	[NVKM_ENGINE_NVENC1  ] = "nvenc1",
89677dec6eSriastradh 	[NVKM_ENGINE_NVENC2  ] = "nvenc2",
90677dec6eSriastradh 	[NVKM_ENGINE_NVDEC0  ] = "nvdec0",
91677dec6eSriastradh 	[NVKM_ENGINE_NVDEC1  ] = "nvdec1",
92677dec6eSriastradh 	[NVKM_ENGINE_NVDEC2  ] = "nvdec2",
93d350ecf5Sriastradh 	[NVKM_ENGINE_PM      ] = "pm",
94d350ecf5Sriastradh 	[NVKM_ENGINE_SEC     ] = "sec",
95677dec6eSriastradh 	[NVKM_ENGINE_SEC2    ] = "sec2",
96d350ecf5Sriastradh 	[NVKM_ENGINE_SW      ] = "sw",
97d350ecf5Sriastradh 	[NVKM_ENGINE_VIC     ] = "vic",
98d350ecf5Sriastradh 	[NVKM_ENGINE_VP      ] = "vp",
99d350ecf5Sriastradh };
100d350ecf5Sriastradh 
101d350ecf5Sriastradh void
nvkm_subdev_intr(struct nvkm_subdev * subdev)102d350ecf5Sriastradh nvkm_subdev_intr(struct nvkm_subdev *subdev)
103d350ecf5Sriastradh {
104d350ecf5Sriastradh 	if (subdev->func->intr)
105d350ecf5Sriastradh 		subdev->func->intr(subdev);
106d350ecf5Sriastradh }
107d350ecf5Sriastradh 
108d350ecf5Sriastradh int
nvkm_subdev_info(struct nvkm_subdev * subdev,u64 mthd,u64 * data)109677dec6eSriastradh nvkm_subdev_info(struct nvkm_subdev *subdev, u64 mthd, u64 *data)
110677dec6eSriastradh {
111677dec6eSriastradh 	if (subdev->func->info)
112677dec6eSriastradh 		return subdev->func->info(subdev, mthd, data);
113677dec6eSriastradh 	return -ENOSYS;
114677dec6eSriastradh }
115677dec6eSriastradh 
116677dec6eSriastradh int
nvkm_subdev_fini(struct nvkm_subdev * subdev,bool suspend)117d350ecf5Sriastradh nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend)
118d350ecf5Sriastradh {
119d350ecf5Sriastradh 	struct nvkm_device *device = subdev->device;
120d350ecf5Sriastradh 	const char *action = suspend ? "suspend" : "fini";
121d350ecf5Sriastradh 	s64 time;
122d350ecf5Sriastradh 
123d350ecf5Sriastradh 	nvkm_trace(subdev, "%s running...\n", action);
124d350ecf5Sriastradh 	time = ktime_to_us(ktime_get());
125d350ecf5Sriastradh 
126d350ecf5Sriastradh 	if (subdev->func->fini) {
127d350ecf5Sriastradh 		int ret = subdev->func->fini(subdev, suspend);
128d350ecf5Sriastradh 		if (ret) {
129d350ecf5Sriastradh 			nvkm_error(subdev, "%s failed, %d\n", action, ret);
130d350ecf5Sriastradh 			if (suspend)
131d350ecf5Sriastradh 				return ret;
132d350ecf5Sriastradh 		}
133d350ecf5Sriastradh 	}
134d350ecf5Sriastradh 
135677dec6eSriastradh 	nvkm_mc_reset(device, subdev->index);
136d350ecf5Sriastradh 
137d350ecf5Sriastradh 	time = ktime_to_us(ktime_get()) - time;
138320c0621Sriastradh 	nvkm_trace(subdev, "%s completed in %"PRId64"us\n", action, time);
139d350ecf5Sriastradh 	return 0;
140d350ecf5Sriastradh }
141d350ecf5Sriastradh 
142d350ecf5Sriastradh int
nvkm_subdev_preinit(struct nvkm_subdev * subdev)143d350ecf5Sriastradh nvkm_subdev_preinit(struct nvkm_subdev *subdev)
144d350ecf5Sriastradh {
145d350ecf5Sriastradh 	s64 time;
146d350ecf5Sriastradh 
147d350ecf5Sriastradh 	nvkm_trace(subdev, "preinit running...\n");
148d350ecf5Sriastradh 	time = ktime_to_us(ktime_get());
149d350ecf5Sriastradh 
150d350ecf5Sriastradh 	if (subdev->func->preinit) {
151d350ecf5Sriastradh 		int ret = subdev->func->preinit(subdev);
152d350ecf5Sriastradh 		if (ret) {
153d350ecf5Sriastradh 			nvkm_error(subdev, "preinit failed, %d\n", ret);
154d350ecf5Sriastradh 			return ret;
155d350ecf5Sriastradh 		}
156d350ecf5Sriastradh 	}
157d350ecf5Sriastradh 
158d350ecf5Sriastradh 	time = ktime_to_us(ktime_get()) - time;
159320c0621Sriastradh 	nvkm_trace(subdev, "preinit completed in %"PRId64"us\n", time);
160d350ecf5Sriastradh 	return 0;
161d350ecf5Sriastradh }
162d350ecf5Sriastradh 
163d350ecf5Sriastradh int
nvkm_subdev_init(struct nvkm_subdev * subdev)164d350ecf5Sriastradh nvkm_subdev_init(struct nvkm_subdev *subdev)
165d350ecf5Sriastradh {
166d350ecf5Sriastradh 	s64 time;
167d350ecf5Sriastradh 	int ret;
168d350ecf5Sriastradh 
169d350ecf5Sriastradh 	nvkm_trace(subdev, "init running...\n");
170d350ecf5Sriastradh 	time = ktime_to_us(ktime_get());
171d350ecf5Sriastradh 
172d350ecf5Sriastradh 	if (subdev->func->oneinit && !subdev->oneinit) {
173d350ecf5Sriastradh 		s64 time;
174d350ecf5Sriastradh 		nvkm_trace(subdev, "one-time init running...\n");
175d350ecf5Sriastradh 		time = ktime_to_us(ktime_get());
176d350ecf5Sriastradh 		ret = subdev->func->oneinit(subdev);
177d350ecf5Sriastradh 		if (ret) {
178d350ecf5Sriastradh 			nvkm_error(subdev, "one-time init failed, %d\n", ret);
179d350ecf5Sriastradh 			return ret;
180d350ecf5Sriastradh 		}
181d350ecf5Sriastradh 
182d350ecf5Sriastradh 		subdev->oneinit = true;
183d350ecf5Sriastradh 		time = ktime_to_us(ktime_get()) - time;
184320c0621Sriastradh 		nvkm_trace(subdev, "one-time init completed in %"PRId64"us\n", time);
185d350ecf5Sriastradh 	}
186d350ecf5Sriastradh 
187d350ecf5Sriastradh 	if (subdev->func->init) {
188d350ecf5Sriastradh 		ret = subdev->func->init(subdev);
189d350ecf5Sriastradh 		if (ret) {
190d350ecf5Sriastradh 			nvkm_error(subdev, "init failed, %d\n", ret);
191d350ecf5Sriastradh 			return ret;
192d350ecf5Sriastradh 		}
193d350ecf5Sriastradh 	}
194d350ecf5Sriastradh 
195d350ecf5Sriastradh 	time = ktime_to_us(ktime_get()) - time;
196320c0621Sriastradh 	nvkm_trace(subdev, "init completed in %"PRId64"us\n", time);
197d350ecf5Sriastradh 	return 0;
198d350ecf5Sriastradh }
199d350ecf5Sriastradh 
200d350ecf5Sriastradh void
nvkm_subdev_del(struct nvkm_subdev ** psubdev)201d350ecf5Sriastradh nvkm_subdev_del(struct nvkm_subdev **psubdev)
202d350ecf5Sriastradh {
203d350ecf5Sriastradh 	struct nvkm_subdev *subdev = *psubdev;
204d350ecf5Sriastradh 	s64 time;
205d350ecf5Sriastradh 
206d350ecf5Sriastradh 	if (subdev && !WARN_ON(!subdev->func)) {
207d350ecf5Sriastradh 		nvkm_trace(subdev, "destroy running...\n");
208d350ecf5Sriastradh 		time = ktime_to_us(ktime_get());
209d350ecf5Sriastradh 		if (subdev->func->dtor)
210d350ecf5Sriastradh 			*psubdev = subdev->func->dtor(subdev);
211d350ecf5Sriastradh 		time = ktime_to_us(ktime_get()) - time;
212320c0621Sriastradh 		nvkm_trace(subdev, "destroy completed in %"PRId64"us\n", time);
213*149bda8eSriastradh 		mutex_destroy(&subdev->mutex);
214d350ecf5Sriastradh 		kfree(*psubdev);
215d350ecf5Sriastradh 		*psubdev = NULL;
216d350ecf5Sriastradh 	}
217d350ecf5Sriastradh }
218d350ecf5Sriastradh 
219d350ecf5Sriastradh void
nvkm_subdev_ctor(const struct nvkm_subdev_func * func,struct nvkm_device * device,int index,struct nvkm_subdev * subdev)220d350ecf5Sriastradh nvkm_subdev_ctor(const struct nvkm_subdev_func *func,
221677dec6eSriastradh 		 struct nvkm_device *device, int index,
222d350ecf5Sriastradh 		 struct nvkm_subdev *subdev)
223d350ecf5Sriastradh {
224d350ecf5Sriastradh 	const char *name = nvkm_subdev_name[index];
225d350ecf5Sriastradh 	subdev->func = func;
226d350ecf5Sriastradh 	subdev->device = device;
227d350ecf5Sriastradh 	subdev->index = index;
228d350ecf5Sriastradh 
229d350ecf5Sriastradh 	__mutex_init(&subdev->mutex, name, &nvkm_subdev_lock_class[index]);
230d350ecf5Sriastradh 	subdev->debug = nvkm_dbgopt(device->dbgopt, name);
231d350ecf5Sriastradh }
232