1 /* $NetBSD: nouveau_nvkm_engine_pm_nv40.c,v 1.3 2021/12/18 23:45:37 riastradh Exp $ */ 2 3 /* 4 * Copyright 2013 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_engine_pm_nv40.c,v 1.3 2021/12/18 23:45:37 riastradh Exp $"); 28 29 #include "nv40.h" 30 31 static void 32 nv40_perfctr_init(struct nvkm_pm *pm, struct nvkm_perfdom *dom, 33 struct nvkm_perfctr *ctr) 34 { 35 struct nvkm_device *device = pm->engine.subdev.device; 36 u32 log = ctr->logic_op; 37 u32 src = 0x00000000; 38 int i; 39 40 for (i = 0; i < 4; i++) 41 src |= ctr->signal[i] << (i * 8); 42 43 nvkm_wr32(device, 0x00a7c0 + dom->addr, 0x00000001 | (dom->mode << 4)); 44 nvkm_wr32(device, 0x00a400 + dom->addr + (ctr->slot * 0x40), src); 45 nvkm_wr32(device, 0x00a420 + dom->addr + (ctr->slot * 0x40), log); 46 } 47 48 static void 49 nv40_perfctr_read(struct nvkm_pm *pm, struct nvkm_perfdom *dom, 50 struct nvkm_perfctr *ctr) 51 { 52 struct nvkm_device *device = pm->engine.subdev.device; 53 54 switch (ctr->slot) { 55 case 0: ctr->ctr = nvkm_rd32(device, 0x00a700 + dom->addr); break; 56 case 1: ctr->ctr = nvkm_rd32(device, 0x00a6c0 + dom->addr); break; 57 case 2: ctr->ctr = nvkm_rd32(device, 0x00a680 + dom->addr); break; 58 case 3: ctr->ctr = nvkm_rd32(device, 0x00a740 + dom->addr); break; 59 } 60 dom->clk = nvkm_rd32(device, 0x00a600 + dom->addr); 61 } 62 63 static void 64 nv40_perfctr_next(struct nvkm_pm *pm, struct nvkm_perfdom *dom) 65 { 66 struct nvkm_device *device = pm->engine.subdev.device; 67 struct nv40_pm *nv40pm = container_of(pm, struct nv40_pm, base); 68 69 if (nv40pm->sequence != pm->sequence) { 70 nvkm_wr32(device, 0x400084, 0x00000020); 71 nv40pm->sequence = pm->sequence; 72 } 73 } 74 75 const struct nvkm_funcdom 76 nv40_perfctr_func = { 77 .init = nv40_perfctr_init, 78 .read = nv40_perfctr_read, 79 .next = nv40_perfctr_next, 80 }; 81 82 static const struct nvkm_pm_func 83 nv40_pm_ = { 84 }; 85 86 int 87 nv40_pm_new_(const struct nvkm_specdom *doms, struct nvkm_device *device, 88 int index, struct nvkm_pm **ppm) 89 { 90 struct nv40_pm *pm; 91 int ret; 92 93 if (!(pm = kzalloc(sizeof(*pm), GFP_KERNEL))) 94 return -ENOMEM; 95 *ppm = &pm->base; 96 97 ret = nvkm_pm_ctor(&nv40_pm_, device, index, &pm->base); 98 if (ret) 99 return ret; 100 101 return nvkm_perfdom_new(&pm->base, "pc", 0, 0, 0, 4, doms); 102 } 103 104 static const struct nvkm_specdom 105 nv40_pm[] = { 106 { 0x20, (const struct nvkm_specsig[]) { 107 {} 108 }, &nv40_perfctr_func }, 109 { 0x20, (const struct nvkm_specsig[]) { 110 {} 111 }, &nv40_perfctr_func }, 112 { 0x20, (const struct nvkm_specsig[]) { 113 {} 114 }, &nv40_perfctr_func }, 115 { 0x20, (const struct nvkm_specsig[]) { 116 {} 117 }, &nv40_perfctr_func }, 118 { 0x20, (const struct nvkm_specsig[]) { 119 {} 120 }, &nv40_perfctr_func }, 121 {} 122 }; 123 124 int 125 nv40_pm_new(struct nvkm_device *device, int index, struct nvkm_pm **ppm) 126 { 127 return nv40_pm_new_(nv40_pm, device, index, ppm); 128 } 129