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