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